Mensaje de error al migrar el almacén de Core Data

El problema:

Tengo un código bastante simple (a continuación) que provoca una exception durante ' migratePersistentStore ' con el post de error

 Exception:*** -[__NSArrayM replaceObjectAtIndex:withObject:]: object cannot be nil 

El código:

 NSPersistentStore * oldStore = [_persistentStoreCoordinator persistentStores][0]; if (oldStore) { @try { [_persistentStoreCoordinator migratePersistentStore:oldStore toURL:[self storeURL] options: @{ NSPersistentStoreRemoveUbiquitousMetadataOption : @YES } withType:NSSQLiteStoreType error:&error]; } @catch(NSException* ex) { NSLog(@"Exception:%@", ex.description); } } 

Informacion adicional:

  • Parece que si no hay datos, la exception no se produce. En cambio, la misma function establece un error, con userInfo " No se puede agregar la misma tienda dos veces ".
  • Actualmente estoy haciendo un pequeño proyecto simple para intentar replicar el problema, publicaré un enlace aquí una vez que esté listo.

Aparentemente, a Core Data no le gusta la migration cuando su URL de iCloud y su URL local son iguales. Pensé que esto no debería importar porque realmente, los datos de iCloud se almacenan en su propio directory. PERO, parece que durante la migration, usar el mismo nombre provoca problemas.

Solución sencilla: simplemente haz algo como esto:

 - (NSURL *)storeURL { NSURL * documentsDirectory = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:NULL]; if (iCloudEnabled]) { return [documentsDirectory URLByAppendingPathComponent:@"iCloudEventData.sqlite"]; } else { return [documentsDirectory URLByAppendingPathComponent:@"EventData.sqlite"]; } } 

Realmente no hay suficiente información aquí para indicarte la causa exacta. Como puede haber adivinado, CoreData se está encontrando con un problema en el que está reemplazando un object en una matriz con un object nulo. Esto puede suceder si sus models de mapeo no coinciden correctamente.

Para solucionar su problema, debe hacer dos cosas:

  1. Quite ese try / catch y establezca un punto de corte simbólico para todas las excepciones. Esto hará que el depurador se detenga cuando llegue a esta exception, y podrá ver el rastreo de stack y todo lo demás que está sucediendo en su aplicación. Tenga en count que si CoreData se ejecuta en conflictos de fusión, estos se manejan dentro de CoreData como excepciones y el depurador también se detendrá en esos. En ese caso, simplemente continúe hasta que su matriz de excepciones.

  2. Establezca los arguments de inicio de su aplicación para activar el logging de migration para ver cómo llega a este punto. En Xcode, edite la tarea Ejecutar del esquema de aplicación para pasar -com.apple.CoreData.MigrationDebug . Tenga en count que el guión que precede al argumento es importante. CoreData registrará lo que sucede durante su migration, lo que debería ayudar a identificar el problema.

¿Cuál debería ser tu esquema?

Una conjetura aleatoria: ¿tiene alguna subclass NSManagedObject declarada en su model que olvidó include una implementación en su compilation? En ese caso, es imaginable que el código de migration pueda intentar crear una instancia de la subclass personalizada, no lo haga, y luego no verificará si tuvo éxito antes de lanzar el resultado en una matriz.

Ejecute sin una migration y realice algo como esto para comprobar:

 for(NSEntityDescription *entityDescription in model.entities) { NSString *className = [entityDescription managedObjectClassName]; Class class = NSClassFromString(className); if(className && !class) NSLog(@"An implementation of class %@ is missing from the build", className); }