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 […] By Ray Wenderlich.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 2 of this article. Click here to view the first page.

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_*”.

So add this new method to ListViewController.m:

- (void)loadNotes {
    
    NSURL *ubiq = [[NSFileManager defaultManager] 
        URLForUbiquityContainerIdentifier:nil];
    
    if (ubiq) {
        
        self.query = [[NSMetadataQuery alloc] init];
        [self.query setSearchScopes:
            [NSArray arrayWithObject:
                NSMetadataQueryUbiquitousDocumentsScope]];
        NSPredicate *pred = [NSPredicate predicateWithFormat: 
            @"%K like 'Note_*'", NSMetadataItemFSNameKey];
        [self.query setPredicate:pred];
        [[NSNotificationCenter defaultCenter] addObserver:self 
            selector:@selector(queryDidFinishGathering:) 
            name:NSMetadataQueryDidFinishGatheringNotification 
            object:self.query];
        
        [self.query startQuery];
        
    } else {
        
        NSLog(@"No iCloud access");
        
    }
    
}

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.

So add the following line of code to the end of viewDidLoad:

[[NSNotificationCenter defaultCenter] addObserver:self 
    selector:@selector(loadNotes) 
    name: UIApplicationDidBecomeActiveNotification object:nil];

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:


- (void)queryDidFinishGathering:(NSNotification *)notification {
    
    NSMetadataQuery *query = [notification object];
    [query disableUpdates];
    [query stopQuery];
    
    [self loadData:query];
    
    [[NSNotificationCenter defaultCenter] removeObserver:self 
        name:NSMetadataQueryDidFinishGatheringNotification
        object:query];
    
    self.query = nil;
    
}

This is exactly the same as we added earlier in the tutorial. Next, add the implementation of loadData as follows (right above queryDidFinishGathering):

- (void)loadData:(NSMetadataQuery *)query {
    
    [self.notes removeAllObjects];
    
    for (NSMetadataItem *item in [query results]) {
        
        NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
        Note *doc = [[Note alloc] initWithFileURL:url];
        
        [doc openWithCompletionHandler:^(BOOL success) {
            if (success) {
                
                [self.notes addObject:doc];
                [self.tableView reloadData];
                                
            } else {
                NSLog(@"failed to open from iCloud");
            }
            
        }];        
    }    
} 

The loadData method has to populate the array of notes according to the results of the query. The implementation here fully reloads the list of notes as returned by iCloud.

One final change. For testing purposes, go ahead and add a ‘refresh’ button to the navigator item which triggers the loadNotes method when tapped, by adding this code to the bottom of viewDidLoad:

UIBarButtonItem *refreshItem = [[UIBarButtonItem alloc] 
    initWithTitle:@"Refresh"                                                                 
    style:UIBarButtonItemStylePlain                                                              
    target:self 
    action:@selector(loadNotes)];
self.navigationItem.leftBarButtonItem = refreshItem;

That’s it! Compile and run the app on one device, and create a few notes. Then start the app on another device, and see that the table is correctly populated with the same notes!

Where To Go From Here?

Here is a example project with all of the code from the above tutorial.

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

Over 300 content creators. Join our team.