This is part 3 in my iCloud tutorial series – the previous article is iCloud 2: Setting up an application for iCloud
Before I start digging into the code, I thought I’d write about how devices communicate with iCloud – the types of data and metadata that are shared bet we the iCloud infrastructure and the various platforms. There’s not a lot of information on this, so I thought it would be helpful to include this into the tutorial.
The types of data that are stored in iCloud
There are two types of data that you store in iCloud
- Key-value objects (property lists)
- Documents – files and directories
The following figure illustrates these types of data.
iCloud synchronization (Source: Apple.com)
Key-value storage is designed for holding small amounts of data which you access through key-value bindings. Think of this as a property list or dictionary – you ask for an object using a key and get the object (or nil if no object for that key exists). A good use of this is for storing application settings for sharing between devices.
This is obviously not meant for storing a lot of data. In fact, Apple limits it to 64 KB per application. That’s kilobytes, not gigabytes.
Document storage is where most of the interesting storage is going on in iCloud. Typically you store files that your user generates in the application. For example, in NotePlus, this is the notes and audio files that are created when the user creates a note.
Let’s consider a single file that is in iCloud. There are two components associated with this file:
- Metadata: information about the file, such as its name, versioning information and the number of bytes of data in it;
- Data: the actual contents of the file
The idea is that metadata is very small in relation to the overall data for the file, and that an application can easily contain all the metadata for all the files stored in iCloud. Any changes to the metadata of a file on a device are pushed back to the iCloud servers. When you create a file on a device, iCloud will also pull that file to the server.
Conversely, on a device pulling a file is managed by the operating system and the application in tandem. You should assume that your application will request a file that is not on the device and then it will be pulled down (there are scenarios where the OS will pull down files, but this has not been documented by Apple). This is good in terms of managing the amount of space you need for an application; the cost is that now opening a file is an asynchronous operation with a noticeable lag. This latency may be long enough that you cannot just put everything on hold until you have finished the operation – for example, if you are doing a file open and read in the middle of a multi-player game the lag might be long enough that your character gets killed while waiting. Not good. The good thing is that your application will be able to determine if a file is local or not, and you, as the developer, can handle this accordingly.
Data and efficiency
iCloud initially uploads the entire file from a device. When the user makes a change to the file, then iCloud sends only the changes back to the server to create a new version of the document. The following illustrate this action:
The device wants to push a new version of a file to iCloud, ...
... Changes in the file are identified, ...
... the changes are uploaded and a new version of the file is created.
(Note: The source code for the non-iCloud version of NotePlus is available by clicking this link.)
I’m not going to change gears and talk a little more about the NotePlus application. When I wrote NotePlus I tried to follow the Model-View-Controller (MVC) design pattern as best I could. I have several data objects that represent the text of a note (NpNoteText) and the audio associated with the note (NpNoteAudio). A class, NpNoteManager, provides an interface to get a list of note names and to manage notes by providing interfaces to add and remove them from the system.
The master (note list) screen for NotePlus (NpMasterViewController)
The NotePlus app is a Universal Master-Detail application. On the iPad this is represented as a split-view controller; on the iPhone this is done by relying on the navigation controller mechanism to navigate to a note. The two main screen objects are the master controller (NpMasterViewController) which displays the list of all the notes, and NpDetailViewController, which provides the interface for editing a note and recording and playing the audio associated with the note. On the iPad one or both controller may be visible.
Editing a note in NotePlus (NpDetailViewController)
On NpMasterViewController’s navigation bar are buttons to create a new note and to edit the notes (which only supports deleting notes). A user may also delete a note by swiping from left to right on the note in the list. The advantage of metadata is obvious in an application like NotePlus. Populating the list inNpMasterViewController only needs the metadata, not the full note information.
NpDetailController is the note editor. This class contains a UITextView for editing the text of the note and a UIToolbar that has buttons for recording and playing audio. It supports both landscape and portrait orientations.
One more data class I have is NpNoteConfiguration. This is a simple class that keeps track of the last note the user opened. This is used mostly for remembering the user’s state when the user quits the application and returns.
Where do we go from here
Now that I have introduced the NotePlus application, I will start to update it to incorporate iCloud into the application. The steps I will need to take are:
- Determine if iCloud is available or not;
- Access the metadata for all the files (for the master screen);
- Load a note from iCloud storage (including resolving conflicts);
- Save a note and synchronize it with iCloud.
Again, the source code for the initial version of NotePlus is available here.
Until next time!
Next: Determining if iCloud is available.