Je suis assez nouveau à Coredata et cette application qui l'utilise. Et je travaille actuellement sur une fonctionnalité qui efface toutes les données de base lorsque je me déconnecte dans l'application.
J'ai 2 fichiers SQLLITE (pour une raison quelconque, ils pensaient que c'était pratique) p>
Comment peut-on Je dégage les deux fichiers de toutes les données et les réinitialisez-les dans un état de référence? P>
J'ai essayé de nombreuses façons, à la suite de guides, à ce jour. P>
Comment effacer / réinitialiser toutes les Coredata dans une relation à une ou plusieurs a> p> Comment supprimer tous les objets du noyau Data P> Ils semblent tous échouer pour moi.
Maintenant, je me demande ce que je fais mal? Et peut-être que quelqu'un peut m'expliquer comment réinitialiser mes 2 fichiers Coredata de la manière appropriée. P> EDIT: P> - (NSManagedObjectContext *)managedObjectContext
{
  if (_managedObjectContext != nil) {
    return _managedObjectContext;
  }
  Â
  NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
  if (coordinator != nil) {
    _managedObjectContext = [[NSManagedObjectContext alloc] init];
    [_managedObjectContext setPersistentStoreCoordinator:coordinator];
  }
  return _managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil) {
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyName" withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
NSString *storePath = [[self applicationDocumentsDirectory]
stringByAppendingPathComponent:@"MyName.sqlite"];
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"MyName" ofType:@"momd"];
if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
}
}
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
//Check to see what version of the current model we're in. If it's >= 2.0,
//then and ONLY then check if migration has been performed...
NSSet *versionIdentifiers = [[self managedObjectModel] versionIdentifiers];
DLog(@"Which Current Version is our .xcdatamodeld file set to? %@", versionIdentifiers);
if ([versionIdentifiers containsObject:@"2.0"])
{
BOOL hasMigrated = YES;
if (hasMigrated==YES) {
storePath = nil;
storePath = [[self applicationDocumentsDirectory]
stringByAppendingPathComponent:@"MyName2.sqlite"];
}
}
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
NSError *error;
NSDictionary *pscOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption,
nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeUrl
options:pscOptions
error:&error]) {
DLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
4 Réponses :
J'utilise cette fonction dans l'Appdelegate de l'une de mes applications ...
- (void)deleteAllCoreData { NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores[0]; NSError *error; NSURL *storeURL = store.URL; NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator; [storeCoordinator removePersistentStore:store error:&error]; [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error]; __persistentStoreCoordinator = nil; __managedObjectContext = nil; __managedObjectModel = nil; [self addDefaultData]; }
Ouais, bien genre de. Le problème est cependant que cela ne fonctionne pas pour moi.
Qu'est-ce qui ne fonctionne pas? Quelles erreurs obtenez-vous? Comment savez-vous que cela ne fonctionne pas.
Je n'ai aucune erreur que ce soit. Mais je remarque lorsque je me déconnecte et reconnectez-vous sous un autre compte que toutes les données stockées dans la Coredata du compte précédent sont toujours là et visibles.
Ajoutez-vous les données dans le début de l'application?
Le seul moyen d'ajouter des données aux données de base consiste à apporter un appel à un serveur. Mais je ne fais pas d'appels de serveur à des fins de test ATM afin que les données soient totalement vides.
Pas sûr alors. Si vous testez, êtes-vous sûr que vous utilisez un nouvel objet pour les tests? Cela fonctionne parfaitement pour moi. Prend 50 000 autres enregistrements dans différentes tables et l'enlève tout en une fraction d'une seconde.
Sans voir de code, je ne peux pas m'empêcher d'autres. Le code que j'ai posté fonctionne comme je l'utilise pour faire exactement cela. Si quelque chose d'autre dans votre code n'est pas configuré à droite, cela peut causer un problème.
de code est affiché dans ma question maintenant. Peut-être que vous pouvez découvrir ce que c'est? Peut-être une chose de migration?
Votre exemple de code recherche uniquement des erreurs de removeImatPath: Erreur: code>. Qu'en est-il de l'appel à
RemovePersistentStore: Erreur: code>? Votre code ignore la valeur de retour de cet appel et le paramètre d'erreur. Je parie que ça échoue et il serait bon de savoir pourquoi.
Si votre application peut créer les fichiers, supprimez-les simplement lorsque l'application quitte. Si vous avez une notion d'une base de données contenant des informations de schéma précieuses et que vous devez simplement tronquer le fichier, ce n'est pas vraiment le cas dans les données de base ... Le schéma est dans les modèles d'entité compilée et les fichiers XCWHATEVER. p>
De plus, je dois simplement avoir le problème, car si vous souhaitez que les données de base ne soient pas persistantes, vous utilisez le mauvais outil. P>
Je ne suis pas d'accord avec votre dernière déclaration. Les données de base ont beaucoup plus d'avantages que de persistance. Il est normal d'avoir une partie du modèle persistant et une autre pièce transitoire à l'aide de nsinmemorystoretype code>. C'est pourquoi c'est là, non?
OFC Je veux que mes données soient persistantes. Voulez-vous simplement tout effacer lorsque vous vous déconnectez avec votre compte. Qui est un cas rare mais pas un que je devrais ignorer. Un utilisateur est automatiquement connecté après avoir enregistré ou connecté à un moment donné. Et ne peut se déconnecter que manuellement. Qui est un acte de conscience de l'utilisateur pour effacer les données locales de cet utilisateur particulier. Donc, je dois être préparé pour un nouveau (ou le même) utilisateur quand il se connecte.
@imartin, je suppose que vous pouvez l'utiliser sans un magasin persistant persistant ... pour la gestion des annulations peut-être ... mais c'est certainement un cas d'utilisation moins convaincante.
@GraDyPlayer Il y a plus que des annonces de gestion: relations inverse, kvo, versions, ... (à l'avenir peut-être peut-être travailler iCloud Sync). J'ai généralement peu d'entités persistantes et que le reste se trouve dans un magasin en mémoire. Juste quelques clics pour les persister (si je le décide ainsi) sans avoir besoin de modifier quoi que ce soit.
Je ne suis pas un détracteur de données de base, mais tout ce que vous recevez de données de base est assez trivial à l'implémentation et est livré avec un poids lourd d'avoir à tout courir sur un seul fil ou effectuer un verrouillage, ou la mise à jour de la notification fusion folle.
Essayez la méthode suivante pour affleurer la base de données, cela fonctionne parfaitement pour moi.
C'est à peu près la même chose que d'autres réponses données. Malheureusement, ils ne travaillent pas pour moi.
Faites une chose, appliquez un point de rupture sur la méthode de la flushdatabase et accédez à votre «/ Library / Application \ Prise en charge / iPhone \ Simulator» et ouvrez la base de données à l'aide de SQLITEMANAPER ou LITA et consultez les entrées de base de données et lorsque la méthode de la base de données encombrature est Exécuté Actualisez la base de données, vous verrez que votre base de données est complètement rinçue. S'il vous plaît mettre à jour moi quand vous faites ce débogage.
Je fais ce débogage maintenant. J'ai 2 fichiers sqlite. On est presque vide "db2.sqlite". L'autre a les données qui me semblent bien familières de l'application "dB.sqlite". Aucun d'entre eux ne reçoit ses données supprimées après la méthode Flush.
Je doute que vous n'ayez pas le bon gérantObjectContext avec vous, lorsque vous appelez la méthode de la flushdatabase.
Bien! Bonnes nouvelles. Tu avais raison. Appartement, il y avait un deuxième objet de MOC qui a été déclaré quelque part. Au moment où j'ai accédé et inséré cet objet dans le flush, j'ai vu les 2 dBfiles étant retirés de mon chercheur et ont vu les résultats sur mon écran. Encore une fois, hurray pour le code de la héritage de merde ...... Merci de votre aide, cela m'a beaucoup aidé.
NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator; [storeCoordinator removePersistentStore:store error:&error]; [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error]; So you're removing the persistent store from the persistent store coordinator, and then trying to delete the file. But just removing the store from the coordinator isn't enough to guarantee that the file associated with the store has been closed, and if it hasn't then the file system will probably prevent you from deleting the file. I can't tell from your question whether you're using ARC here, but since you say that it's old code there's a good chance that you aren't. Either way, if removing the store causes it to be autoreleased instead of released, or if you keep any other references to the store anywhere, then the store won't be deallocated just because you removed it from the coordinator, the file may remain open, and deleting the file will fail.A good way to see what's really going on, in addition to looking at the error object provided by -removeItemAtPath:error:, is to take a look in the file system and see whether the file is still there after you try to remove it. Go to the Organizer window, select your device and application, and download a copy of the app's sandbox. You should then be able to see whether the file is really being deleted.If you do see that the files are being deleted as you think they should be, then look for other ways that the data may be restored. If UserA logs out and then UserB logs into the app while it's still running, are you sure that you've started with a fresh managed object context? Is it possible that UserA's data remains in the MOC? It could then be written out when you create and add a new store. Another possibility that occurs to me is that iCloud is "helping" here. I see that your data files are kept in the Documents directory, and iOS will normally try to keep files in that directory backed up to iCloud. Perhaps when you create a new store for UserB's data, iCloud adds UserA's records back to that store. (Seems unlikely -- I'm pretty sure iCloud is more sophisticated than that -- but something to check.)
Ok laissez-moi effacer les choses un peu. 1. L'ARC est utilisé dans l'application, les fonctions de libération et les fonctions d'autorelease ne sont jamais utilisées. Lorsque je "déconnecter", je ne détecte aucun changement dans le système de fichiers que ce soit. iCloud n'est pas impliqué non plus. Le MOC est un bon coup. Je ne suis pas certain de savoir comment cela est géré dans l'application. Pouvez-vous me dire comment je devrais le gérer?
La première chose que je peux voir, c'est que vous définissez toutes vos trucs CoreData à Nil à l'intérieur de la boucle. Cela doit être don après que la boucle ait fini de courir.
Ne fonctionne pas de toute façon. Ce que je remarque, c'est que seul l'un des 2 magasins est en train d'être enregistré. Qu'est-ce qui pourrait être une raison pour le second ne pas être à l'intérieur de la boucle?
Lorsque vous configurez les données de base, cela ne devrait avoir qu'un magasin de toute façon. Ce magasin tiendra toutes vos données (sauf si vous faites quelque chose qui nécessite spécifiquement plus d'un)?
C'est tout le code hérité. Et tout est un gâchis. Et je viens de commencer à creuser dans cette application. Pour une raison quelconque, il y a 2 fichiers SQLLITE de Coredata et il y a un soupçon de fonction de migration. Mais je ne vois pas besoin de 2 magasins non plus.
Ah, je vois. Avez-vous le code qui met en place et initialise la pile de Coredata? Je peux peut-être essayer de déchiffrer ce qui se passe.
Depuis que je suis nouveau dans ce truc de Coredata, je ne suis pas sûr de regarder en premier. Et l'application est un désordre total, il ne dispose pas d'une couche de contrôleur, mais aussi tout ce qui est principalement possible, des vues, des modèles, une couche de données, peu importe. Donc, je ne suis pas sûr de quoi rechercher. Je vois l'init du magasin et le managementObject au moins
Habituellement, vous auriez une méthode comme - (NsmanieDObjectContext *) GestionedObjectContext ... dans l'Appdelegate de là, il créerait le contexte de Coredata. Si ce n'est pas là, trouve alors où GestionObjectContext est créé et configuré.
J'ai posté à la fois et le coordinateur du magasin
Pourquoi les appels de Coredata sont-ils toujours toujours dans le délégué de l'application? N'est-il pas beaucoup plus propre de faire une classe dédiée pour la manipulation de Coredata pour votre application et laissez-le créer le gérantObjectContext et les goûts?
Oui tu as raison. Je suppose que je le fais juste parce que c'est là qu'il est défini comme défaut sur un projet Coredata. Serait beaucoup mieux de le mettre dans une classe Singleton distincte.
Mes pensées exactement <3. C'est probablement la première chose que je change quand j'en ai la chance. Créez-moi des contrôleurs Singleton et transférez les appels de Coredata / les appels de serveur / et les données de Disc les gérant les choses dès que possible. ATM Il est juste placé au hasard où qu'ils puissent être utilisés pour cette période au moment où il était nécessaire. Un très mauvais moyen de construire une application imho. Et je suis plutôt déçu que je dois faire face à cette merde de nettoyage, au lieu de me rendre utile ........
Dans votre première inscription, vous effectuez quelques appels différents qui prennent des paramètres
& error code> et vous ne vérifiez ni l'un d'entre eux. Jetez un coup d'œil, voyez quoi (si quelque chose) ces appels essaient de vous parler de ce qui s'est mal passé.
Je suis désolé de vous être confus là-bas. J'ai enregistré mes objets d'erreur pour leur contenu, tout simplement pas dans la pièce de code que j'ai publié. Laissez-moi le mettre à jour et vous dire que l'objet d'erreur est une valeur nulle.