ios iphone sqlite core-data ios-app-extension

Acceso a la base de datos SQL de Core Data en la extensión iOS 8(compartir datos entre la aplicación y la extensión de widgets)



iphone sqlite (4)

Problema:

No se puede acceder a la base de datos Core Data de la aplicación desde una extensión de widgets en la vista actual.

La aplicación en sí misma puede leer y escribir en la base de datos como es normal en iOS 8, pero la extensión no podrá crear la tienda, dando el error, incapaz de escribir en el archivo.

El registro es el siguiente:

Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" reason = "Failed to create file; code = 2


Cambio

[MagicalRecord setupCoreDataStackWithStoreNamed:@"Database"];

a

- (void)setupCoreDataStack { if ([NSPersistentStoreCoordinator MR_defaultStoreCoordinator] != nil) { return; } NSManagedObjectModel *model = [NSManagedObjectModel MR_defaultManagedObjectModel]; NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.yourgroup"]; storeURL = [storeURL URLByAppendingPathComponent:@"Database.sqlite"]; [psc MR_addSqliteStoreNamed:storeURL withOptions:nil]; [NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:psc]; [NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:psc]; }


Descubrí que los archivos del grupo de aplicaciones no tienen una copia de seguridad con el procedimiento de copia de seguridad estándar de iOS.

Tenga en cuenta que el usuario puede perder todos sus datos de la aplicación después de restaurar iOS si mantiene la tienda persistente en un contenedor de grupo de aplicaciones.

ACTUALIZAR

rdar: // 18750178

ACTUALIZAR

parece arreglado en iOS 8.1, los chicos de Apple me enviaron un mensaje y me pidieron que verificara el problema en iOS 8.1, ya sea que lo arreglaran o no (¿bastante descarado no?). No lo he probado, así que tenlo en cuenta. De todos modos, mantener el almacenamiento en AppGroups es una idea muerta en caso de que esté soportando un iOS 8.0 defectuoso


Lo mismo para Swift:

private func setupCoreDataStack() { if NSPersistentStoreCoordinator.MR_defaultStoreCoordinator() != nil { return } let managedObjectModel = NSManagedObjectModel.MR_defaultManagedObjectModel() let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel) var storePath = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier(PBOSharedSuiteGroupName) storePath = storePath!.URLByAppendingPathComponent("AppName.sqlite") var error: NSError? persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storePath, options: nil, error: &error) NSPersistentStoreCoordinator.MR_setDefaultStoreCoordinator(persistentStoreCoordinator) NSManagedObjectContext.MR_initializeDefaultContextWithCoordinator(persistentStoreCoordinator) }

Recuerde adjuntar este método a ambos: AppDelegate y Today Extension


Los widgets no pueden acceder al directorio NSDocuments, que es donde uno normalmente almacenaría su base de datos.

La solución es crear primero un grupo de aplicaciones

Vaya a: Proyecto - Objetivo - Grupos de aplicaciones - Agregar nuevo contenedor

Nombre el contenedor, es decir, ''group.mycontainer''

Repita el proceso para el objetivo del widget usando el mismo nombre para el contenedor.

Luego escribe tu base de datos en tu contenedor de grupo.

Asi que:

NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSAllDomainsMask] lastObject]; storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];

Se convierte en:

NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"]; storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];

Y la inicialización de la tienda debería ser así:

NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"]; storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"]; NSPersistentStore *store = nil; store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]