Copia de security de .sqlite (datos básicos)

Tengo una aplicación basada en datos básicos que utiliza Dropbox para hacer copys de security y restaurar datos. La forma en que respaldo es bastante sencillo. Copio el file .sqlite en el dropbox del usuario.

Ahora mi copy de security y la funcionalidad de restauración funcionan bien. El problema es con el file .sqlite en sí. Parece que el file .sqlite está incompleto .

Ingresé aproximadamente 125 inputs en mi request y tomé una copy de security. La copy de security apareció en mi dropbox pero cuando uso una herramienta de explorador .sqlite para ver el contenido, solo veo los loggings hasta la 117ª input.

Traté de actualizar la primera input y luego de nuevo observando el file .sqlite pero sin cambios.

Lo que es aún más extraño es que la aplicación parece haber registrado todos los cambios. Cuando agrego una input nueva o actualizo una existente y reinicio la aplicación, los datos recién agregados parecen persistir. Pero estos datos recién agregados no aparecen en mi file .sqlite.

Estoy respaldando usando este código:

AppDelegate *appDelegate = [[UIApplication shanetworkingApplication] delegate]; NSString *filePath = [[[appDelegate applicationDocumentsDirectory] path] stringByAppendingPathComponent:@"MyApp.sqlite"]; if (account) { if ([filesystem isShutDown]) { filesystem = [[DBFilesystem alloc] initWithAccount:account]; [DBFilesystem setShanetworkingFilesystem:filesystem]; } DBPath *newPath = [[DBPath root] childPath:[NSString stringWithFormat:@"Backup - %@.sqlite", [NSDate date]]]; DBFile *file = [[DBFilesystem shanetworkingFilesystem] createFile:newPath error:nil]; [file writeContentsOfFile:filePath shouldSteal:NO error:nil]; [filesystem shutDown]; } 

También copié el file .sqlite de la carpeta del simulador y traté de verlo en el browser .sqlite. Todavía muestra el mismo comportamiento. ¿Alguna razón por la que esto debe estar sucediendo?

A partir de iOS 7 / OS X 10.9, Core Data utiliza "Registro de input anticipada" (WAL, por sus siglas en inglés) como modo de logging por defecto para el file de almacenamiento SQLite subyacente. Esto se explica en

Preguntas y respuestas técnicas QA1809: Nuevo modo de logging por defecto para almacenes SQLite de Core Data en iOS 7 y OS X Mavericks

Con el modo WAL, Core Data mantiene intacto el file de la tienda principal y agrega transactions a un file -wal en la misma location. Una vez que se guarda el context de Core Data, el file -wal no se elimina y los datos de ese file tampoco se combinan con el file de tienda. Por lo tanto, simplemente hacer copys del file de la tienda probablemente causará pérdida de datos e inconsistencia.

Eso debería explicar por qué su file .sqlite solo está incompleto. Como solución puede (también explicado en esa nota técnica):

  • Deshabilite el modo WAL (y use el modo de logging de retroceso "antiguo") para el almacén de SQLite configurando el

     @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}}; 

    opción al agregar la tienda persistente o

  • Utilizar el

     - (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store toURL:(NSURL *)URL options:(NSDictionary *)options withType:(NSString *)storeType error:(NSError **)error 

    método para hacer una copy de security del almacén de Core Data.