Beginning iCloud in iOS 5 Tutorial Part 2

Note from Ray: This is the tenth iOS 5 tutorial in the iOS 5 Feast! This tutorial is a free preview chapter from our new book iOS 5 By Tutorials. Enjoy! This is a post by iOS Tutorial Team member Cesare Rocchi, a UX designer and developer specializing in web and mobile applications. This is […]

This simply stores the current document and updates the text view according to the new content received.

In general substituting the old content with the new one is NOT a good practice. When we receive a notification of change from iCloud we should have a conflict resolution policy to enable the user to accept/refuse/merge the differences between the local version and the iCloud one. We’ll discuss more about conflict resolution later, but for now to keep things simple we’ll just overwrite each time.

Next, implement textViewDidChange to notify iCloud when the document changes, and modify the app to refresh the data in viewWillAppear as well:

As above this is not a great practice, because we are going to notify each iCloud about every single change (i.e. each time a character is added or deleted). For efficiency, it would be better to just tell iCloud every so often, or when the user has finished a batch of edits.

There’s just one last step remaining – we need to add the code to send the “noteModified” notification we registered for in viewDidLoad. The best place in this case is the Note class’s loadFromContents:ofType:error, method which is called whenever data are read from the cloud.

So open up Note.m and add this line of code to the bottom of loadFromContents:ofType:error (before the return YES):

Now we are really ready! The best way to test this application is the following: install it on two devices and run it on both. You should be able to edit on one and see the changes periodically propagated to the other.

The propagation of changes is not immediate and might depend on your connectivity. In general, for our examples, it should take 5-30 seconds. Another way to check the correctness it to browse the list of files in your iCloud.

If the application works correctly you should see the note we created in our app:

The ‘unknown’ label comes from the fact that the application has not been uploaded and approved on the Apple Store yet.

Also note that users can delete files from iCloud from this screen at-will (without having to go through your app). So keep this in mind as you’re developing.

Congrats – you have built your first iCloud-aware application!

Handling Multiple Documents

Cool, our example works and we are a bit more acquainted with the capabilities of iCloud. But what we have right now isn’t enough to impress our users, or build an application that makes sense. Who wants to manage just one document?!

So next we are going to extend our application to manage more than one document at a time. The most natural development of our current prototype is to transform it into a notes application, as follows:

The application will start with a view showing a list of notes

Each note will have a unique id

Tapping a note will show a single note view with the content

Users can then edit the content

The list of notes is updated when we launch the application or tap a refresh button

We will reuse some of the code of the previous project but we will need to reorganize it. Let’s start by rearranging the user interface.

Reorganizing the User Interface

In our new project a single view is not enough, we’ll need two. The first will be a table view which shows the list of notes. The second will be pretty similar to the main view of the previous project: it will show an editable text view.

Let’s add a empty table view controller, and modify our app to show that first inside a navigation controller.

Create a new file with the iOS\Cocoa Touch\UIViewController subclass template, name the class ListViewController, and make it a subclass of UITableViewController. You can leave both checkboxes unchecked.

Then open AppDelegate.m, and import ListViewController.h at the top of the file:

#import "ListViewController.h"

Then replace the first few lines of application:didFinishLaunchingWithOptions with the following:

Here we’ve added an array to store the notes, a reference to the old view controller we created we’ll be pushing onto the stack, a metadata query we’ll use to load the notes, and a loadNotes method we’ll write later.

Next switch over to ListViewController.m and synthesize properties at the top of the file:

This initializes the notes array to an empty list, sets up a title for this view controller, and adds a button to the navigation bar that says “Add”. When the user taps this, the addNote method will be called, and we’ll implement this to add a new note.

Unlike the previous project that had just one document (so always used the same filename each time), this time we’re storing multiple documents (one for each note created), so we need a way to generate unique file names. As an easy solution, we will use the creation date of the file and prepend the ‘Note_’ string.

You should be pretty familiar with this code. The file name is generated by combining the current date and hour. We call the saveToURL method and, in case of success, we add the newly created note to the array which populates the table view.

Almost done with the ability to add notes – just need to add the code to populate the table view with the contents of the notes array. Implement the table view data source methods like the following:

Compile and run the application, and you should be able to add new notes when you tap the Add button. You can also go to the iCloud manager in settings to verify they are actually in iCloud.

But what if we quit the application and restart it? The list is empty! We need in fact a way to load them at startup or when the application becomes active.

Loading Notes

To load notes, we’ll follow a similar strategy to what we did earlier when loading a single note. However, this time we don’t know the exact file name, so we have to tweak our search predicate to look for a file name like “Note_*”.

We might be tempted to place a call to this loadNotes method in viewDidLoad. That would be correct, but that is executed on initial app startup. If we want to reload data really each time the app is opened (even from the background), it’s better to add an observer to listen when the application becomes active.

This calls the loadNotes method we just wrote on statup (or when the application returns from the background). And we set up loadNotes to call queryDidFinishGathering when the metadata search completes, so add the code for that next:

Where To Go From Here?

Congratulations, you now have hands-on experience with the basics of using iCloud and the new UIDocument class, to create an iCloud-enabled app with multi-document support.

We’ve just scratched the surface of iCloud. If you are interested in learning more about iCloud, check our our book iOS 5 By Tutorials – the final version will have an additional chapter that covers handling conflict resolution, using NSFileWrapper, storing simple key-value pairs, and using Core Data with iCloud!

If you have any comments or questions on this tutorial or on iCloud in general, please join the forum discussion below!

This is a post by iOS Tutorial Team member Cesare Rocchi, a UX designer and developer specializing in web and mobile applications. He runs Studio Magnolia, an interactive studio that creates compelling web and mobile applications.

Contributors

Ray is part of a great team - the raywenderlich.com team, a group of over 100 developers and editors from across the world. He...

Author

Note from Ray: This is the tenth iOS 5 tutorial in the iOS 5 Feast! This tutorial is a free preview chapter from our new book iOS 5 By Tutorials. Enjoy! This is a post by iOS Tutorial Team member Cesare Rocchi, a UX designer and developer specializing in web and mobile applications. This is […]