Problème:
Impossible d'accéder à la base de données Core Data de l'application à partir d'une extension de widget dans la vue Aujourd'hui.
L'application elle-même est capable de lire et d'écrire dans la base de données comme d'habitude sous iOS 8, mais l'extension ne parviendra pas à créer le magasin, donnant l'erreur, incapable d'écrire dans le fichier.
Le journal est le suivant:
Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)"
reason = "Failed to create file; code = 2
Les widgets ne peuvent pas accéder au répertoire NSDocuments, qui est l'endroit où l'on stocke normalement sa base de données.
La solution consiste à créer d'abord un groupe d'applications
Allez à: Projet - Cible - Groupes d'applications - Ajouter un nouveau conteneur
Nommez le conteneur, c'est-à-dire 'group.mycontainer'
Répétez le processus pour la cible du widget en utilisant le même nom pour le conteneur.
Ensuite, écrivez votre base de données dans votre conteneur de groupe.
Donc:
NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSAllDomainsMask] lastObject];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
Devient:
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
Et l'initialisation du magasin devrait ressembler à ceci:
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]
Je viens de comprendre que les fichiers du groupe d'applications ne sont pas sauvegardés à l'aide de la procédure de sauvegarde iOS standard.
Gardez à l'esprit que l'utilisateur peut perdre toutes ses données d'application après la restauration d'iOS si vous conservez le magasin persistant dans un conteneur de groupe d'applications.
MISE À JOUR
rdar: // 18750178
MISE À JOUR
semble résolu dans iOS 8.1, Apple m'ont envoyé un message et ont demandé de vérifier le problème dans iOS 8.1, qu'il soit corrigé ou non (assez impudent non?). Je ne l'ai pas testé, alors gardez à l'esprit. Quoi qu'il en soit, conserver le stockage dans AppGroups est une idée morte au cas où vous prendriez en charge iOS 8.0 défectueux
Changement
[MagicalRecord setupCoreDataStackWithStoreNamed:@"Database"];
à
- (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];
}
La même chose pour 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)
}
N'oubliez pas d'attacher cette méthode aux deux: AppDelegate et Today Extension