2011-12-31 12 views
26

Estoy tratando de que iCloud trabaje con mi aplicación, que necesita migrar una tienda local existente a una tienda ubicua, si el usuario lo solicita.Sincronización de una tienda Core Data existente con iCloud

Después de husmear un poco en torno a los foros de desarrolladores de Apple y en otros lugares, he adoptado este enfoque, que no funciona de manera coherente. De hecho, lo he visto funcionar, pero solo después de varios bloqueos en el Dispositivo B (que se llena desde iCloud).

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
    if (persistentStoreCoordinator != nil) 
    return persistentStoreCoordinator; 

    NSURL *legacyStoreUrl = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:[self activeStoreFilenameUpgraded:NO]]]; 
    NSURL *upgradedStoreUrl = [NSURL fileURLWithPath:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:[self activeStoreFilenameUpgraded:YES]]]; 

persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 

    if ((IOS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"5.0")) && (self.iCloudEnabled)) { 
    NSPersistentStoreCoordinator* psc = persistentStoreCoordinator; 

    NSFileManager *fileManager = [NSFileManager defaultManager]; 

    NSDictionary *cloudOptions = nil; 
    NSDictionary *localOptions = [NSDictionary dictionaryWithObjectsAndKeys: 
            [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
            [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
            nil]; 


    NSURL *cloudURL = [fileManager URLForUbiquityContainerIdentifier:@"<CONTAINER ID>"]; 
    NSString *coreDataCloudContent = [[cloudURL path] stringByAppendingPathComponent:[NSString stringWithFormat:@"logs%d",[self activeStoreIndex]]]; 
    if ([coreDataCloudContent length] != 0) { 
     // iCloud is available 
     cloudURL = [NSURL fileURLWithPath:coreDataCloudContent]; 

     cloudOptions = [NSDictionary dictionaryWithObjectsAndKeys: 
         [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
         [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
         @"MyAppStore", NSPersistentStoreUbiquitousContentNameKey, 
         cloudURL, NSPersistentStoreUbiquitousContentURLKey, 
         nil]; 
    } else { 
     // iCloud is not available 
    } 

    NSError *error = nil; 
    [psc lock]; 
    if(migrateStore) { 
     migrateStore = NO; 

     NSPersistentStore *srcPS = [psc addPersistentStoreWithType:NSSQLiteStoreType 
      configuration:nil 
      URL:legacyStoreUrl 
      options:localOptions 
      error:&error]; 
     if (![psc migratePersistentStore:srcPS 
      toURL:upgradedStoreUrl 
      options:cloudOptions 
      withType:NSSQLiteStoreType 
      error:&error]) { 
      NSLog(@"Error migrating data: %@, %@/%@/%@", error, [error userInfo], legacyStoreUrl, upgradedStoreUrl); 
      abort(); 
     } 
    } 
    else { 
     if (![psc addPersistentStoreWithType:NSSQLiteStoreType 
      configuration:nil 
      URL:upgradedStoreUrl 
      options:(cloudOptions ? cloudOptions : localOptions) 
      error:&error]) { 
       NSLog(@"Unresolved iCloud error %@, %@", error, [error userInfo]); 
       abort(); 
     } 
    } 
    [psc unlock]; 

    [[NSNotificationCenter defaultCenter] postNotificationName:@"RefetchAllDatabaseData" object:self userInfo:nil]; 
    } else { 
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
          [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
          nil]; 

    NSError *error = nil; 
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:legacyStoreUrl options:options error:&error]) { 
     // error 
     abort(); 
    }  
    } 

    return persistentStoreCoordinator; 
} 
+0

Solo una nota que la aplicación casi siempre tiene una sola tienda; el código para manejar el caso de 2 tiendas (activeStoreIndex, etc.) es un caso marginal. – ed94133

+1

¿Dónde se define migrateStore y se le asigna? – Jim

Respuesta

6

iCloud Core La sincronización de datos está terriblemente rota. Una solución de terceros más confiable es TICoreDataSync; this fork tiene soporte para sincronizar con iCloud, sin depender de la implementación de sincronización de datos centrales de iCloud. Simplemente usa iCloud para sincronizar archivos y maneja la sincronización del objeto Core Data por sí mismo.

Dejé de utilizar la sincronización de datos centrales de iCloud y en su lugar he estado compilando mi aplicación con esta biblioteca; hasta ahora ha estado funcionando muy bien, sin ninguno de los problemas que vi con la implementación de Apple.

+0

La TICDS no se está desarrollando activamente. Desarrollé un nuevo marco, [Ensembles] (http://ensembles.io), basado en los mismos principios, y contabilizando las lecciones aprendidas con TICDS. –

2

me di por vencido en la integración de iCloud, al menos por ahora. No creo poder ofrecer a mis usuarios una solución de sincronización confiable a través de iCloud, dado el desempeño errático de Core Data. Tengo esperanza para iOS 5.1.

+4

La compañía para la que trabajé también quería la integración de iCloud en una aplicación existente con datos centrales, aunque les dije que no funcionaba correctamente. ¡Fue como el infierno! Después del lanzamiento en febrero recibimos muchos comentarios negativos sobre fallas y pérdida de datos. La compañía se declaró insolvente en agosto: D Solo quería contar la historia ... –