Обновления координационных данных ios не видны в разных контекстах управляемых объектов - данные в разных контекстах различаются

У нас возникает проблема, когда разные потоки видят разные данные в одних и тех же записях, но с разными контекстами управляемых объектов (moc). Наше приложение синхронизируется в фоновом режиме с серверным API. Вся синхронизация выполняется в собственном потоке и с использованием собственного moc. Однако мы обнаружили, что при обновлении данных в основном файле moc это изменение данных не отображается в фоновом файле moc. Есть идеи, что могло случиться? Вот еще несколько деталей: мы используем grand central dispatch, например, чтобы поместить операции синхронизации в свой собственный поток: мы проверили, в какой очереди выполняются вещи, и все это происходит в ожидаемой очереди.

- (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];
            });
        }

    }); 
}

вот как мы создаем фоновый moc, и мы подтвердили, что он создан в фоновой очереди.

- (NSManagedObjectContext*)backgroundObjectContext {

    if (_backgroundObjectContext)
        return _backgroundObjectContext;

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

    return _backgroundObjectContext;
}

Я должен добавить, что наш фоновый moc запрашивает данные, и те записи, которые возвращаются из этого действия, по-прежнему имеют старые значения для некоторых полей. Как фоновый moc получает текущие данные, которые уже были сохранены основным moc? Я думал, что просто запросив, я получу текущее состояние этих записей ..

под запросом я имею в виду следующее: фоновый MOC выполняет другой «запрос» для получения «свежих» данных после того, как записи были изменены основным moc, но данные имеют старые значения, а не обновленные значения, видимые в основном 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];
}

Мы очень ценим вашу помощь, поскольку мы пытаемся разобраться в этом или найти решение, которое не включает в себя отключение наших обсуждений на несколько дней.


person Erica F    schedule 10.08.2011    source источник


Ответы (2)


Вот как это должно работать - действительно, важная роль контекста управляемого объекта - защитить вас от изменений данных, сделанных в других потоках. Представьте себе хаос, который произошел бы, если бы у вас был фоновый поток, изменяющий те же объекты, что и основной поток, без какой-либо схемы синхронизации.

Чтобы узнать, как чтобы объединить изменения из одного контекста в другой.

person Caleb    schedule 10.08.2011
comment
Спасибо за вашу помощь. Думаю, меня удивило то, что мы запрашиваем записи, но не получаем текущие данные. Мы только что обнаружили, что при выполнении этого [[ICCoreDataController sharedInstance] backgroundObjectContext] reset]; на фоне контекста решила наши проблемы. Я все же хотел бы понять это лучше. Спасибо!! - person Erica F; 10.08.2011

Я использую следующий код для прослушивания изменений в контексте 2, чтобы контекст 1 оставался актуальным:

  NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
  [nc addObserver:context1
         selector:@selector(contextTwoUpdated:)
             name:NSManagedObjectContextDidSaveNotification
           object:context2];

он вызывает вызов этого метода в контексте 1, и я вызываю метод слияния:

- (void)contextTwoUpdated:(NSNotification *)notification {
  [context1 mergeChangesFromContextDidSaveNotification:notification];
}

побочным эффектом этого является любой NSFetchedResultsController, который прикреплен к context1, будет отправлять различные сообщения своему делегату, информируя его об изменениях,

Я никогда не пробовал слушать в обоих направлениях, пока пользователь меняет объект, а вы обновляете их для пользователя сзади - я подозреваю, что вам, возможно, придется управлять слияниями, если это так, поскольку это одностороннее (и все управляемое пользователем) для меня я предполагаю, что все обновления действительны

person bshirley    schedule 10.08.2011