Réinitialiser un magasin persistant CoreData
Fondamentalement, ce que j'essaie de faire est d'effacer toutes les données de mon CoreData magasin persistant, puis importer de nouvelles données. Comment voulez-vous faire cela? Il semble que la solution la plus simple est d'appeler [NSPersistentStoreCoordinator removePersistentStore:error:]
et ensuite supprimer le fichier. C'est que les meilleures pratiques disponibles? C'est thread-safe?
Merci beaucoup,
#
Question 0.1: a
Je suis en train de mettre à jour les données dans un CoreData magasin persistant. Mon utilisateur est de voir une vue de la table des données statistiques. Je veux mettre à jour l'application, par la suppression de toutes les données existantes, puis d'importer de nouvelles données. Je voudrais montrer un progrès en vue d'indiquer à l'utilisateur que l'application n'est pas suspendu.
J'ai ajouté ce qui suit resetPersistentStore
méthode dans mon AppDelegate (persistentStoreCoordinator
est donnée à titre indicatif):
//...
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
//...
/**
Returns the persistent store coordinator for the application.
If the coordinator doesn't already exist, it is created and the application's store added to it.
*/
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: kPersistentStoreFilename]];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
/**
* Will remove the persistent store
*/
- (NSPersistentStoreCoordinator *)resetPersistentStore {
NSError *error;
[managedObjectContext lock];
//FIXME: dirty. If there are many stores...
NSPersistentStore *store = [[persistentStoreCoordinator persistentStores] objectAtIndex:0];
if (![persistentStoreCoordinator removePersistentStore:store error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
//Delete file
if (![[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
//Delete the reference to non-existing store
[persistentStoreCoordinator release];
persistentStoreCoordinator = nil;
NSPersistentStoreCoordinator *r = [self persistentStoreCoordinator];
[managedObjectContext unlock];
return r;
}
Alors à mon avis je n' (dans un autre thread depuis que je suis en utilisant MBProgressHUD
:
PatrimoineAppDelegate *appDelegate = (PatrimoineAppDelegate *)[[UIApplication sharedApplication] delegate];
//Delete everything
[appDelegate resetPersistentStore];
Et je reçois un EXC_BAD_ACESS
...
Je ne sais pas CoreData ou le multithreading très bien, peut-être que je suis en train de faire une erreur évidente...
source d'informationauteur
Vous devez vous connecter pour publier un commentaire.
Si votre objectif est de vider le magasin de données et de le recharger à nouveau d'informations, vous pouvez peut-être préférable d'utiliser des NSManagedObjectContext de
reset
puis de le charger de nouvelles données.De NSManagedObjectContext de la documentation
Retrait de la persistance et à l'aide de l'objet géré contexte associé avec le magasin est probablement la cause de l'erreur.
Pour ceux qui tentent ce sur iOS9+, il y a maintenant le
destroyPersistentStoreAtURL
etreplacePersistentStoreAtURL
Api.Toujours pas de travail! Abandon causé par ManagedObjectContext lien invalide persistance magasin. Enfin ça marche si je supprime le ManagedObjectContext et laisser l'application recréer plus tard
Voici ma modification
Voici la solution. Il y a peut être un peu plus élégant options (serrure...) mais celui-ci fonctionne.
Vous pouvez échanger (ou supprimer) un magasin persistant et puis réinitialiser le contexte (assurez-vous que vous récupère à nouveau les objets que vous avez en mémoire):
Je suis en utilisant cette option pour effectuer une importation dans un magasin temporaire sur une file d'attente privée, puis d'écraser le thread principal de stocker et de le recharger à tout quand je suis fini. J'ai été importé dans un contexte enfant, mais la suppression d'objets existants sans effets secondaires est devenu gênant dans mon cas.
Avant de réinitialiser le persistentStore vous devez d'abord réinitialiser tous les managedObjectContext associés avec qui, sinon tous les managedObjects n'aura pas de contexte pour être accessible à ce qui peut être source d'erreur.
il est bon de toujours supprimer le fichier sqlite directement à partir du système de fichiers et de définir managedObjectContext et persistentStoreCoordinator à néantplutôt que d'appeler removePersistentStore.
Cela permettra de recréer le persistantStore et managedObjectContext prochaine fois que vous essayez d'accéder ou de commencer à stocker.
J'ai trouvé la meilleure façon de faire face à ces types de problèmes, aussi longtemps que vous pouvez recharger votre Base de Donnéesest de suivre ces étapes:
(1) Reset du simulateur.
(2) Supprimer la base de données sqlite à partir de votre projet.
(3) Supprimer le simulateur répertoire de votre machine.
Étonnamment, j'ai trouvé que faire les étapes 1 & 2 ne fonctionne pas toujours sans l'étape 3.
Vous devrez recharger votre Base de Données de magasin si vous faites cela.