Search code examples
objective-ccore-dataicloud

Core Data + iCloud how to handle data update from cloud


I try to figure out how to handle the data update from the cloud. In Swift sample application all work "from the box", but in Obj-C I can't update the interface when the application gets updated data from iCloud. Below my code for instantiating container and context:

@synthesize persistentContainer = _persistentContainer;

- (NSPersistentCloudKitContainer *)persistentContainer {
    // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
    @synchronized (self) {
        if (_persistentContainer == nil) {
            _persistentContainer = [[NSPersistentCloudKitContainer alloc] initWithName:@"SampleCloudObjC"];
            NSPersistentStoreDescription *description = [_persistentContainer.persistentStoreDescriptions firstObject];
            [description setOption:@(true) forKey:NSPersistentStoreRemoteChangeNotificationPostOptionKey];
            [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
                if (error != nil) {
                    NSLog(@"Unresolved error %@, %@", error, error.userInfo);
                    abort();
                }
            }];
        }
    }
    
    return _persistentContainer;
}

- (void)saveContext {
    NSManagedObjectContext *context = self.persistentContainer.viewContext;
    context.automaticallyMergesChangesFromParent = YES;
    NSError *error = nil;
    if ([context hasChanges] && ![context save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, error.userInfo);
        abort();
    }
}

And here I try to handle notification:

- (void)viewDidLoad {
    [super viewDidLoad];
    taskList = [Task fetchAll];
    [[NSNotificationCenter defaultCenter] 
        addObserver:self 
        selector:@selector(updateTable)     
        name:NSPersistentStoreRemoteChangeNotificationPostOptionKey 
        object:nil];
}

- (IBAction)updateTable {
    taskList = [Task fetchAll];
    [self.tableView reloadData];
}

Solution

  • As I understood key thing was to make followed changes in code: AppDelegate:

    ...
    NSPersistentStoreDescription *description = [_persistentContainer.persistentStoreDescriptions firstObject];
                [description setOption:@(true) forKey:NSPersistentStoreRemoteChangeNotificationPostOptionKey];
                [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
    ...
    
    

    Controller:

    ...
    [[NSNotificationCenter defaultCenter]
         addObserver:self
         selector:@selector(remoteHandler:)
         name:NSPersistentStoreRemoteChangeNotification
         object:nil];
    ...
    

    Now UI is updating but looks like only after the application goes to the background and back to active.