Class

UIDocument

An abstract base class for managing discrete portions of your app's data.

Overview

Applications that make use of UIDocument and its underlying architecture get many benefits for their documents:

  • Asynchronous reading and writing of data on a background queue. Your application's responsiveness to users is thus unaffected while reading and writing operations are taking place.

  • Coordinated reading and writing of document files that is automatically integrated with cloud services.

  • Support for discovering conflicts between different versions of a document (if that occurs).

  • Safe-saving of document data by writing data first to a temporary file and then replacing the current document file with it.

  • Automatic saving of document data at opportune moments; this mechanism includes support for dealing with suspend behaviors.

In the Model-View-Controller design pattern, a UIDocument object is a model object or model-controller object—it manages the data of a document or the aggregate model objects that together constitute the document's data. You typically pair it with a view controller that manages the view presenting the document’s contents. UIDocument provides no support for managing document views.

Document-based applications include those that can generate multiple documents, each with its own file-system location. A document-based application must create a subclass of UIDocument for its documents. See “Subclassing Notes,” below, for details.

The primary attribute of a document in the UIDocument architecture is its file URL. When you initialize an instance of your document subclass by calling initWithFileURL:, you must pass a file URL locating the document file in the application sandbox. UIDocument determines the file type (the Uniform Type Identifier associated with the file extension) and the document name (the filename component) from the file URL. You can override the accessor methods of the fileType and localizedName properties to supply different values.

The following outlines the life cycle of a typical document (see “Subclassing Notes” for implementation details):

  1. You create a new document or open an existing document.

  2. The user edits the document.

    As the user edits, track changes to the document. UIDocument periodically notes when there are unsaved changes and writes the document data to its file.

  3. The user requests that the document to be integrated with cloud services (optional).

    You must enable the document for cloud storage. You must also resolve any conflicts between different versions of the same document.

  4. The user closes the document.

    Call closeWithCompletionHandler: on the document instance. UIDocument saves the document if there are any unsaved changes.

A typical document-based application calls openWithCompletionHandler:, closeWithCompletionHandler:, and saveToURL:forSaveOperation:completionHandler: on the main thread. When the read or save operation kicked off by these methods concludes, the completion-handler block is executed on the same dispatch queue on which the method was invoked, allowing you to complete any tasks contingent on the read or save operation. If the operation is not successful, NO is passed into the completion-hander block.

Implementation of the NSFilePresenter Protocol

The UIDocument class adopts the NSFilePresenter protocol. When another client attempts to read the document of a UIDocument-based application, that reading is suspended until the UIDocument object is given an opportunity to save any changes made to the document.

Although some implementations do nothing, UIDocument implements all NSFilePresenter methods, . Specifically, UIDocument:

In your UIDocument subclass, if you override a NSFilePresenter method you can always invoke the superclass implementation (super).

Subclassing Notes

Each document-based application must create a subclass of UIDocument whose instances represent its documents. The subclassing requirements for most applications are simple:

  • For writing operations, implement the contentsForType:error: method to provide a snapshot of document data. The data must be in the form of an NSData object (for flat files) or an NSFileWrapper object (for file packages). Writing operations are usually initiated through the autosave feature

  • For reading operations, implement the loadFromContents:ofType:error: method to receives an NSData or NSFileWrapper object and initialize the application's data structures with it.

  • Implement change tracking to enable the autosaving feature. See Change Tracking for details.

  • When cloud services are enabled for a document, resolve conflicts between different versions of a document. See Conflict Resolution and Error Handling for details.

The contentsForType:error: and loadFromContents:ofType:error: methods are typically called on the main queue. More specifically:

If you have special requirements for reading and writing document data for which the contentsForType:error: and loadFromContents:ofType:error: methods won’t suffice, you can override other methods of the UIDocument class. See Advanced Overrides for a discussion of these requirements and methods.

Change Tracking

To enable the autosaving feature of UIDocument, you must notify it when users make changes to a document. UIDocument periodically checks whether the hasUnsavedChanges method returns YES; if it does, it initiates the save operation for the document.

There are two primary ways to implement change tracking in your UIDocument subclass:

  • Call the methods of the NSUndoManager class to implement undo and redo for the document. You can access the default NSUndoManager object from the undoManager property. This is the preferred approach, especially for existing applications that already support undo and redo.

  • Call the updateChangeCount: method at the appropriate junctures in your code.

Conflict Resolution and Error Handling

A UIDocument object has a specific state at any moment in its life cycle. You can check the current state by querying the documentState property, and get notified about changes by observing the UIDocumentStateChangedNotification notification.

If a document is enabled for iCloud, it is important to check for conflicting versions and to attempt to resolve conflicts. Do this by listening for the UIDocumentStateChangedNotification notification and then checking if the document state is UIDocumentStateInConflict. This state indicates that there are conflicting versions of the document, which you can access by calling the NSFileVersion class method unresolvedConflictVersionsOfItemAtURL:, passing in the document’s file URL. If you can resolve a conflict correctly without user interaction, do so. Otherwise, discretely notify the user that a conflict exists and let them choose how to resolve it. Possible approaches include:

  • Displaying the conflicting versions, from which a user can pick one or both versions to keep

  • Displaying a merged version and giving the user an option to pick it

  • Displaying the file modification dates and giving the user the option to choose one or both

Document state, in addition to indicating an inter-file conflict, can indicate errors. For example, UIDocumentStateClosed indicates an error in reading, and UIDocumentStateSavingError indicates an error in saving or reverting a document. Your app is notified of reading and writing errors through the success parameter passed into the completion handlers of the openWithCompletionHandler:, closeWithCompletionHandler:, revertToContentsOfURL:completionHandler:, and saveToURL:forSaveOperation:completionHandler: methods.

You can handle errors by calling or implementing the handleError:userInteractionPermitted: method; this method is called by the default implementations of the openWithCompletionHandler: and saveToURL:forSaveOperation:completionHandler: methods when a UIDocument object encounters a reading or writing error, respectively. You can handle read, save, and reversion errors by informing the user and, if the situation permits, trying to recover from the error.

Be sure to read the description for the contentsForType:error: method for its guidance on handling errors encountered during document saving.

Advanced Overrides

If you application has special requirements for reading or writing document data, it can override methods of UIDocument other than loadFromContents:ofType:error: and contentsForType:error:. These requirements often include the following:

If you override most of these methods be aware that all reading and writing of document data must be done on a background queue and must be coordinated with other attempts to read from and write to the same document file. Because of this, you should usually call the superclass implementation (super) as part of your override, and if you call other UIDocument methods you should usually invoke them in the block passed into a call of the performAsynchronousFileAccessUsingBlock: method. Read the method descriptions for the details.

Thread Safety Considerations

If you override any of the document-attribute properties (listed under Accessing Document Attributes) by overriding the related accessor methods, be aware that the UIKit framework can call these accessor methods on a background thread. Thus your overriding implementation must be thread safe.

Topics

Initializing a Document Object

initWithFileURL:

Returns a document object initialized with its file-system location.

Accessing Document Attributes

fileURL

The file URL with which the document was initialized.

localizedName

The localized name of the document.

fileType

The file type of the document.

fileModificationDate

The date and time the document file was last modified.

documentState

Returns the current state of the document.

progress

The upload or download progress of a document.

Writing Document Data

closeWithCompletionHandler:

Asynchronously closes the document after saving any changes.

contentsForType:error:

Override this method to return the document data to be saved.

saveToURL:forSaveOperation:completionHandler:

Saves document data to the specified location in the application sandbox.

writeContents:andAttributes:safelyToURL:forSaveOperation:error:

Ensures that document data is written safely to a specified location in the application sandbox.

writeContents:toURL:forSaveOperation:originalContentsURL:error:

Writes the document data to disk at the sandbox location indicated by a file URL.

savingFileType

Returns the file type to use for saving a document.

fileAttributesToWriteToURL:forSaveOperation:error:

Returns a dictionary of file attributes to associate with the document file when writing or updating it.

fileNameExtensionForType:saveOperation:

Returns a file extension to append to the file URL of the document file being written.

Reading Document Data

openWithCompletionHandler:

Opens a document asynchronously.

loadFromContents:ofType:error:

Override this method to load the document data into the app’s data model.

readFromURL:error:

Reads the document data in a file at a specified location in the application sandbox.

Accessing Document Files Asynchronously

performAsynchronousFileAccessUsingBlock:

Schedules a document-reading or document-writing operation on a concurrent background queue.

Reverting a Document

revertToContentsOfURL:completionHandler:

Reverts a document to the most recent document data stored on-disk.

Disabling and Enabling Editing

disableEditing

Overridden to disable editing when it is unsafe to make changes to a document.

enableEditing

Overridden to enable editing when it is safe again to make changes to a document.

Tracking Changes and Autosaving

hasUnsavedChanges

Returns whether the document has any unsaved changes.

updateChangeCount:

Update the change counter by indicating the kind of change.

undoManager

The undo manager for the document.

changeCountTokenForSaveOperation:

Overridden to return a change token for a specific save operation.

updateChangeCountWithToken:forSaveOperation:

Overridden to update the change count with reference to a change-count token passed in by UIKit.

autosaveWithCompletionHandler:

Called by UIKit to initiate automatic saving of documents with unsaved changes.

Supporting User Activities

userActivity

An object encapsulating a user activity supported by this document.

restoreUserActivityState:

Restores the state needed to continue the given user activity.

updateUserActivityState:

Updates the state of the given user activity.

Resolving Conflicts and Handling Errors

handleError:userInteractionPermitted:

Called or overridden to handle an error that occurs during an attempt to read, save, or revert a document.

finishedHandlingError:recovered:

Tells UIKit that you have finished handled the error.

userInteractionNoLongerPermittedForError:

Sent when it is no longer safe to proceed without immediately handling the error.

Constants

UIDocumentChangeKind

Constants for specifying the kind of change to a document.

UIDocumentSaveOperation

Constants for specifying the type of save operation.

UIDocumentState

The document state.

NSUserActivityDocumentURLKey

The key identifying the document associated with a user activity.

Notifications

UIDocumentStateChangedNotification

Posted by the document object when there is a change in the state of the document.

Relationships

Inherits From

See Also

Documents

UIManagedDocument

A managed document object that integrates with Core Data.