Search code examples
core-dataios7icloudnsnotificationcenter

None of the iCloud Notifications Are Firing in my iOS 7 App


I'm new to Core Data and iCloud, but I've managed to get both working (mostly). My data is syncing between iOS devices, but I don't know when. :)

I'm trying to listen for when changes are available from iCloud so I can refresh my UI.

I set up Core Data and iCloud in my app delegate like this: http://d.pr/n/SxmZ Most of that is sample code I have applied, but it seems to work well.

In a separate view controller, where I'm displaying app data, I have set up my notification like this:

- (void)viewDidLoad
{
  [super viewDidLoad];

  //Register notifications
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatesAvailable) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:nil];
}

- (void)updatesAvailable{
  //This never fires...
  NSLog(@"Update available...");
  [PPStatusBar showSuccessWithStatus:@"Update available..."];
}

So here are my questions:

  1. If all that iCloud stuff gets set up in my app delegate, does that mean it's available to use everywhere? Or do I have to re-initialize my persistent store coordinator in every view controller where I want to listen for notifications?
  2. I am planning to re-query my entity in that updatesAvailable method, so has the data from iCloud made it all the way into the Core Data object graph by the time NSPersistentStoreDidImportUbiquitousContentChangesNotification is called?
  3. Is it safe to assume that small, single-record changes should be propagating between two iOS devices within 10 seconds?

I have tried this between two iOS 7 devices, in addition to the iOS 7 Simulator, and still no luck. I have also managed to get iCloud key/value change listeners work great, it's just not working with Core Data.

Thanks in advance for your help. :)


Solution

  • It looks like the problem is in your addObserver call. The object is nil but it should be your persistent store coordinator. For example:

    [notificationCentre addObserver:self
                           selector:@selector(CoreData_StoreDidImportUbiquitousContentChanges:)
                               name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
                             object:coordinator];
    

    Which then calls a notification handler structured like this:

    - (void)CoreData_StoreDidImportUbiquitousContentChanges:(NSNotification*) notification {
    }
    

    To answer your specific questions:

    1. The persistent store, managed object context etc will be accessible elsewhere. However, be aware that the managed object context is not threadsafe. You should only ever access it from the same thread.
    2. The new data should be accessible at the time you receive the notification. The NSNotification object itself can also be used if you only want to know about the new data. It contains details of all changed objects grouped based on if they were created, odified or deleted.
    3. The propagation time seems very variable. The simulator allows you to request a sync (Cmd+I) but I'm not aware of a similar mechanism on an actual device. If you are currently debugging one of the running devices however you will be able to see activity to/from iCloud in Xcode.

    One further note. The import notification will come in on a different thread to your user interface. If you want to make any UI changes (eg. refreshing) then you will need to use something like this to make sure they run on the UI thread:

    dispatch_async(dispatch_get_main_queue(), ^{
        // Refresh UI here
    });