Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ios coredata updates not seen on different managed object contexts - data is different between contexts

We're having this issue where different threads see different data on the same records but with different managed object contexts (moc). Our app syncs in the background to a server API. All of the syncing is done on it's own thread and using it's own moc. However, we've discovered that when data gets updated on the main moc that change in data is not shown in the background moc. Any ideas what could be happening? Here's some more details: we're using grand central dispatch like so to put the sync operations on it's own thread: We've checked which queue things are running on and it all is happening on the queue expected.

- (void) executeSync; {

    dispatch_async(backgroundQueue, ^(void) {
        if([self isDebug])
            NSLog(@"ICSyncController: executeSync queue:%@ \n\n\n\n\n", [self queue]);


       for(id <ICSyncControllerDelegate> delegate in delegates){
           [delegate syncController:self];
       }
        if([ICAccountController sharedInstance].isLoggedIn == YES && shouldBeSyncing == YES) {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 300ull * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
                [self executeSync];
            });
        }

    }); 
}

here's how we create the background moc and we've confirmed that it's created on the background queue.

- (NSManagedObjectContext*)backgroundObjectContext {

    if (_backgroundObjectContext)
        return _backgroundObjectContext;

    _backgroundObjectContext = [[NSManagedObjectContext alloc] init];    
    [_backgroundObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
    [_backgroundObjectContext setStalenessInterval:0.0];

    return _backgroundObjectContext;
}

I should add that our background moc is requerying for data and those records returned from that action still have the old values for some fields. How does the background moc get the current data that was already saved by the main moc? I thought just by requerying I would get the current state of these records..

by requerying I mean the following: The background MOC is executing another "query" to get "fresh" data after the records have been changed by the main moc, yet the data has old values - not the updated values seen in the main moc.

+ (NSArray *)dirtyObjectsInContext:(NSManagedObjectContext *)moc {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SUBQUERY(memberships, $m, $m.category.name == %@ AND $m.syncStatus > %d).@count > 0", MANAGED_CATEGORY_FAVORITES, ManagedObjectSynced];

    return [self managedObjectsWithPredicate:predicate inContext:moc];
}

Your help is hugely appreciated as we've been trying to figure this out, or find a work around that doesn't include ditching our threads for days now.

like image 468
Erica F Avatar asked Aug 10 '11 19:08

Erica F


1 Answers

That's how it's supposed to work -- indeed, an important role of the managed object context is to protect you from changes to the data made in other threads. Imagine the havoc that would result if you had a background thread modifying the same objects that the main thread was using without some sort of synchronization scheme.

Read Communicating Changes Between Contexts to learn how to merge changes from one context into another.

like image 101
Caleb Avatar answered Sep 30 '22 22:09

Caleb