2011-08-10 23 views
5

Estamos teniendo este problema donde diferentes subprocesos ven diferentes datos en los mismos registros pero con diferentes contextos de objetos administrados (moc). Nuestra aplicación se sincroniza en segundo plano con una API de servidor. Toda la sincronización se realiza en su propio hilo y utilizando su propio moc. Sin embargo, hemos descubierto que cuando los datos se actualizan en el moc principal, el cambio en los datos no se muestra en el moc de fondo. ¿Alguna idea de lo que podría estar pasando? Aquí hay algunos detalles más: estamos usando el despacho de Grand Central como para poner las operaciones de sincronización en su propio hilo: hemos comprobado en qué cola se están ejecutando las cosas y todo está sucediendo en la cola esperada.ios actualizaciones de coredatos no vistas en diferentes contextos de objetos administrados - los datos son diferentes entre contextos

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

    }); 
} 

Así es como creamos el moc de fondo y hemos confirmado que se creó en la cola de fondo.

- (NSManagedObjectContext*)backgroundObjectContext { 

    if (_backgroundObjectContext) 
     return _backgroundObjectContext; 

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

    return _backgroundObjectContext; 
} 

debo añadir que nuestra moc fondo es volver a consultar los datos y los registros devueltos desde que la acción todavía tienen los viejos valores de algunos campos. ¿Cómo obtiene el moc de fondo los datos actuales que ya guardó el moc principal? Pensé que solo con la consulta obtendría el estado actual de estos registros ...

al volver a consultar Me refiero a lo siguiente: El MOC de fondo está ejecutando otra "consulta" para obtener datos "nuevos" después de que los registros hayan sido cambiados por el moc principal, sin embargo, los datos tienen valores antiguos, no los valores actualizados que se ven en el moc principal.

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

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

Su ayuda se agradece enormemente, ya que hemos estado tratando de resolver esto, o encontrar un trabajo en torno a que no incluye abandonando nuestros hilos desde hace días.

Respuesta

4

Así es como se supone que funciona, de hecho, una función importante del contexto del objeto administrado es protegerlo de los cambios en los datos hechos en otros hilos. Imagine los estragos que resultarían si tuviera un hilo de fondo que modificara los mismos objetos que el hilo principal estaba usando sin algún tipo de esquema de sincronización.

Lea Communicating Changes Between Contexts para obtener información sobre cómo combinar los cambios de un contexto a otro.

+1

Gracias por su ayuda. Supongo que la sorpresa para mí fue que estamos solicitando registros, pero no recibimos los datos actuales. Acabamos de descubrir que al hacer esto [[[ICCoreDataController sharedInstance] backgroundObjectContext] reset]; en el contexto de fondo resolvió nuestros problemas. Sin embargo, aún me gustaría entender esto mejor. ¡¡Gracias!! –

4

uso el siguiente código para escuchar los cambios en el contexto 2, de modo que el contexto 1 mantiene al día:

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

que hace que este método a ser llamado el contexto 1, e invoco el método de combinación :

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

un efecto secundario de esto es cualquier NSFetchedResultsController que se adjunta a context1 enviará una variedad de mensajes a su delegado informándole de los cambios,

nunca intenté escuchar en ambos sentidos mientras el usuario cambia el objeto y los actualiza en el usuario desde atrás. Sospecho que es posible que tenga que administrar las fusiones si ese es el caso, ya que es unidireccional (y todo manejado por el usuario) para yo asumo que todas las actualizaciones son válidas

Cuestiones relacionadas