Big Bucket Software you like to use
BBCloudController
October 29th, 2011

I’ve been implementing iCloud syncing lately. It’s been tricky, but I’ve mostly got it sorted now. I’ve done my best to encapsulate the complexity in a class called BBCloudController. I’ve uploaded it to my github. Here’s how it works.

First of all, you need to create a class that inherits from UIDocument. A UIDocument is “an abstract base class for managing the data of documents.” I won’t go into how that’s done, you’re better off reading the docs for that. Once you’ve got your UIDocument, you’re pretty much set. In the example below, I’m assuming that there’s a UIDocument subclass called “MyDocument”.

In your application:didFinishLaunchingWithOptions:

// ensures that iCloud storage is available
if ([BBCloudController isSupported])
{
    m_cloudController =
        [[BBCloudController alloc] initWithDocumentClass:[MyDocument class]
                                                filename:@"note.txt"];

    m_cloudController.delegate = self;

    [m_cloudController openOrCreateDocument];
}

That will create a controller encapsulating a document named “note.txt”. The openOrCreateDocument will look for note.txt in the cloud/ubiquity container (using an NSMetadataQuery). If it can’t find it there, it will create it locally and move it there (by calling setUbiquitous).

The openOrCreateDocument method is asynchronous so the BBCloudController‘s delegate will be called once the file has been opened/created. The BBCloudController delegate needs to implement these methods:

-(void)cloudController:(BBCloudController*)controller
       documentDidOpen:(UIDocument*)document
{
    // UIDocument subclasses typically have a delegate. Hook that up here.
    ((MyDocument*)document).delegate = self;
}

-(void)cloudController:(BBCloudController*)controller
  documentFailedToOpen:(UIDocument*)document
{
}

Whenever you want to make a modification to the document:

-(void)makeAModification
{
    MyDocument* document =
        (BBTvForecastDocument*)m_cloudController.document;

    // ...diddle with the document...

    [document updateChangeCount:UIDocumentChangeDone];
}

And that’s pretty much it. When something changes in the cloud, your UIDocument subclass will have its loadFromContents method called on it. It’s up to your UIDocument subclass to notify you when it reloads. If a conflict occurs, the BBCloudController will handle it silently by taking the latest version.

So grab it and let me know how you like it. Please don’t hesitate to let me know if you discover any bugs or can think of how it might be improved. I figure it will get an optional “handleConflict” method in the future but for now, taking the latest version is sufficient for my needs.