Important: This document is not up to date with the latest API and best practices. Developers interested in adopting iCloud should read iCloud Design Guide and consult the references described in that document.
In this tutorial, you created a sophisticated iOS app that used iCloud to save its documents. Designing an app to support iCloud involves many decisions, though, and this tutorial only scratches the surface. This chapter suggests some directions you might take next as you continue to learn about integrating iCloud into your apps.
Handling Document Version Conflicts
Apps that store documents in iCloud must be prepared to handle conflicts between different versions of that document. Conflicts can occur when changes are made to the same document on two different devices. For example, a conflict can occur when the user edits the same document on two different devices that are currently in Airplane Mode, because they are unable to transmit changes to the iCloud servers.
Although conflicts do not happen too often, apps need to be prepared to handle them. To detect conflicts in a document-based app, you must register for the state change notifications of the
UIDocument class. If the document enters the
UIDocumentStateInConflict state, your app needs to retrieve the conflicting document versions and decide how best to proceed.
For more information about handling version conflicts, see iCloud Design Guide.
Displaying Upload and Download Progress to the User
For documents that grow to be large, you might want to provide some feedback to the user when sent to and from iCloud. Instances of the
NSURL class maintain attributes that tell you the current transfer status of the underlying file. You can use these values to determine whether a file is downloaded to the local device and whether changes have been uploaded to iCloud. You can also use these values to check the current progress of download and upload operations.
For information about accessing the iCloud status attributes, see NSURL Class Reference.
Handling Cases in Which iCloud Is Unavailable
One of the advantages of calling the
URLForUbiquityContainerIdentifier: method shortly after launch is that it lets you determine whether iCloud is available early in the life of your app. A return value of
nil from the method means that the iCloud container directory could not be reached—usually because the user’s device is not configured to use iCloud. (During development, being unable to access iCloud usually means there is an error in the configuration of your app’s iCloud entitlements.)
Your app should provide a smooth fallback position in cases when iCloud is unavailable. For example, you might store new user documents in the local sandbox and transfer them to iCloud at the first opportunity. You should do this quietly and not bother the user.
You should also be aware that the user can turn off your app’s access to iCloud altogether by turning off the Documents & Data option or by deleting the current iCloud account. Although this should not happen often, you should still code your apps defensively and be prepared for this kind of change while your app is suspended or running in the background. Specifically, after having moved to the background and returned to the foreground, call the
URLForUbiquityContainerIdentifier: method to verify that iCloud is still available before attempting to access any files or documents in your app’s container directory.
Improving the Document Presentation Interface
The Simple Text Editor app searches for documents and presents them in the order in which they are discovered. However, you might want to provide a more deterministic way of presenting documents in your own apps. For example, you could display them in alphabetical order or maintain a record of the current order and write that information to iCloud as well.
Supporting the Dynamic Naming of Documents
The tutorial used a combination of a static name and a dynamic number for new document names, but your own apps should be more creative. Here are some tips for creating good document names:
Use an initial name that is indicative of the content your app creates. Do not just create “Untitled” documents. Make the document names more specific. For example, a painting program might use “My Creation” or “Canvas” for the base document name.
Provide a simple but unobtrusive way for the user to change document names. Let the user tap the document name and edit it in place. Do not post alerts or use an interface that pulls the user out of the current context.
For documents with text content, consider using that content (instead of the filename) to identify the document. This approach is similar to the way the Notes app displays information. Because users do not have direct access to the underlying file system, displaying the initial document content is often better than displaying a file name.
Supporting the Key-Value Store
If you want your app to share preferences and other noncritical configuration data, use the
NSUbiquitousKeyValueStore class to do so using iCloud. This class behaves in a similar way to the
NSUserDefaults class. It provides a simple interface for setting key-value pair data in iCloud.
For more information about using the
NSUbiquitousKeyValueStore class, see Preferences and Settings Programming Guide.
Using Core Data with iCloud
Core Data provides a set of sophisticated tools for modeling your app’s data structures and managing them efficiently in your app. Unlike live SQLite databases, Core Data stores can be shared among a user’s devices through iCloud. Core Data manages this operation by sending only the changes to iCloud, so that they can be incorporated into local databases on each device.
For more information about using Core Data with iCloud, see “Designing for Core Data in iCloud”.
Learning More About File Coordinators
At some point, you might need to understand more about the role file coordinators play in iCloud. Although the
UIDocument class provides the file coordinator for many actions, some actions may require you to create a file coordinator yourself. For example, when deleting files in Simple Text Editor, you had to create a file coordinator of your own and use it to perform the operation. Therefore, it is important that you understand the role file coordinators play in your app and when you might need to use them.
For more information about when to use file coordinators, see File System Programming Guide.