J'utilise NSFetchedResultsController pour afficher un tas d'objets, qui sont sectionnés en utilisant des dates. Lors d'une nouvelle installation, tout fonctionne parfaitement et les objets sont affichés dans la vue de table. Cependant, il semble que lorsque l'application est relancée, j'obtiens un plantage. Je spécifie un cache lors de l'initialisation de NSFetchedResultsController, et quand je ne le fais pas, cela fonctionne parfaitement.
Voici comment je crée mon NSFetchedResultsController:
- (NSFetchedResultsController *)results {
// If we are not nil, stop here
if (results != nil)
return results;
// Create the fetch request, entity and sort descriptors
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"utc_start" ascending:YES];
NSArray *descriptors = [[NSArray alloc] initWithObjects:descriptor, nil];
// Set properties on the fetch
[fetch setEntity:entity];
[fetch setSortDescriptors:descriptors];
// Create a fresh fetched results controller
NSFetchedResultsController *fetched = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"day" cacheName:@"Events"];
fetched.delegate = self;
self.results = fetched;
// Release objects and return our controller
[fetched release];
[fetch release];
[descriptor release];
[descriptors release];
return results;
}
Voici les messages que je reçois lorsque l'application se bloque:
FATAL ERROR: The persistent cache of section information does not match the current configuration. You have illegally mutated the NSFetchedResultsController's fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'FATAL ERROR: The persistent cache of section information does not match the current configuration. You have illegally mutated the NSFetchedResultsController's fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:'
Je n'ai vraiment aucune idée de pourquoi cela dit cela, car je ne crois pas que je fais quoi que ce soit de spécial qui pourrait causer cela. Le seul problème potentiel est l'en-tête de section (jour), que je construis comme ceci lors de la création d'un nouvel objet:
// Set the new format
[formatter setDateFormat:@"dd MMMM"];
// Set the day of the event
[event setValue:[formatter stringFromDate:[event valueForKey:@"utc_start"]] forKey:@"day"];
Comme je l'ai mentionné, tout cela fonctionne bien s'il n'y a pas de cache impliqué. Toute aide appréciée!
J'ai eu un problème similaire avec l'une de mes applications, lorsque le Apple a publié le nouvel iOS 4.0. Recherche:
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[self managedObjectContext] sectionNameKeyPath:nil cacheName:nil];
Et définissez la valeur du paramètre cacheName sur nil. Cela a fonctionné pour moi, j'espère que ce sera le cas pour vous. Faites le moi savoir.
J'ai commencé à obtenir la même erreur lors de la mise à niveau de MacBook Pro vers Snow Leopard 10.6.4 et le dernier SDK.
Il s'avère que beaucoup d'entre nous utilisaient du code qui n'était pas conforme aux règles, mais nous ne le savions pas parce que CoreData ne se comportait pas vraiment conformément à ses propres règles.
Plus précisément, lorsque vous récupérez des éléments, ils sont mis en cache et, dans la version 4.0, ce cache n'est pas automatiquement purgé dans les cas où il a été purgé dans le SDK précédent.
Pour moi, la solution était simple. Je viens d'employer la méthode de classe qui purge les caches. Vous pouvez spécifier une entité individuelle, mais je spécifie nil donc il les fait tout simplement dans ce morceau particulier de code de démarrage:
[NSFetchedResultsController deleteCacheWithName:nil];
Du coup, la petite application sur laquelle j'ai travaillé uniquement pour me familiariser avec CoreData fonctionne à nouveau.
Directement dans la documentation de NSFetchedResultsController
:
Modification de la demande de récupération
Vous ne pouvez pas simplement modifier la demande d'extraction pour modifier les résultats. Si vous souhaitez modifier la demande de récupération, vous devez:
Si vous utilisez un cache, supprimez-le (en utilisant
deleteCacheWithName:
). En règle générale, vous ne devez pas utiliser de cache si vous modifiez la demande de récupération.Modifiez la demande de récupération.
Appeler
performFetch:
.
J'ai rencontré un problème similaire. Lorsque j'ai inspecté la console du débogueur, elle a montré quels étaient les objets mis en cache et les objets récupérés afin que je puisse comprendre pourquoi ils sont incohérents. Dans mon cas, cela était dû à un prédicat différent.
Étant donné que les valeurs de mon prédicat ne sont pas dynamiques, je pourrais spécifier un nom de cache différent pour chaque prédicat. Cela créera un cache pour chaque "type" que je spécifie.
Je suppose que vous devrez évaluer votre besoin d'avoir le cache. Spécifier nil signifie qu'une extraction est effectuée dans chaque appel.
J'ai compris que l'erreur ne se produit que lorsque la demande de récupération comporte des modifications. Si vous créez un nouveau NSFetchRequest OR modification du prédicat OR descripteur de tri, vous devez supprimer le cache ou utiliser un autre cache. Sinon, assurez-vous que vous avoir la même NSFetchRequest ou assurez-vous que votre NSFetchedResultsController est conservé et cela devrait résoudre votre problème.
Si vous utilisez le simulateur, essayez de le réinitialiser - je suppose que vous avez changé votre carte d'entité et qu'il devient confus par un cache restant. Sinon, vous pouvez essayer de faire ce que l'erreur dit:
- (void)applicationWillTerminate:(UIApplication *)application {
[NSFetchedResultsController deleteCacheNamed:@"Events"];
//etc
}
L'exception se produit toujours avec Xcode 7 (beta 4):
Vous avez illégalement muté la demande d'extraction de NSFetchedResultsController, son prédicat ou son descripteur de tri sans désactiver la mise en cache ni utiliser + deleteCacheWithName:
REMARQUE: Ceci est avec une application iOS maître non détaillée de "modèle" Xcode avec Xcode CoreData standard "plaque de chaudière" code créé avec Xcode 7 et utilisant la dernière cible de déploiement (iOS 9).
Je l'ai remarqué en premier lorsque j'ai redémarré mon application dans le simulateur. J'avais démarré et arrêté l'application plusieurs fois via Xcode et puis c'est arrivé; et ça n'arrêtait pas. J'ai décidé de faire quelques expériences, et les résultats:
Le problème peut toujours être résolu comme suit, en utilisant l'une ou l'autre des méthodes suivantes:
application didFinishLaunchingWithOptions
D'AppDelegate, ajoutez le code suivant Swift NSFetchedResultsController.deleteCacheWithName(nil)
ou Objective-C [NSFetchedResultsController deleteCacheWithName:nil];
. Cela efface le cache corrompu.Je crois également que c'est un artefact de l'exécution via Xcode et de l'arrêt de l'application avant qu'elle ne puisse être nettoyée. Je n'ai pas vu cela dans l'appareil réel.
Pour ceux qui rencontrent le même problème de nos jours, le problème est que, d'une manière ou d'une autre, Core Data ne nettoie pas le cache, donc fonctionne bien la première fois, mais pas après. Ensuite, mettez simplement cette ligne juste après l'init NSFetchRequest
[NSFetchedResultsController deleteCacheWithName:@"Name"];
Quittez-vous le simulateur à l'aide du bouton d'accueil ou en fermant l'application dans Xcode? Peut-être que l'application n'a pas le temps de terminer l'écriture dans le cache. Essayez d'utiliser le bouton d'accueil pour quitter l'application.
J'avais le même problème.
Pour corriger, j'ai mis le [NSFetchedResultsController deleteCacheWithName:@"cacheName"];
avant le lancement de resultsController. Fonctionne pour moi car il n'y va que la première fois.
J'ai trouvé via Ray Wenderlich forums que
Notez qu'il ne se bloque que lorsque la demande de récupération n'est pas encore créée lorsque vous ajoutez quelque chose de nouveau à la banque de données , c'est-à-dire lorsque la vue Emplacements n'est pas encore chargée . Si la vue est déjà chargée, cela fonctionne bien. Bizarre, hein?
Donc, ce qui s'est passé dans mon cas était le suivant:
La solution consiste à s'assurer que La récupération est terminée avant de créer un objet (ce qui affecterait la récupération).
Alternativement, vous pouvez supprimer le cache, mais c'est moins performant pratiquement.
Notez que l'avertissement du débogueur
Vous avez illégalement muté la demande d'extraction de NSFetchedResultsController, son prédicat ou son descripteur de tri sans désactiver la mise en cache ni utiliser + deleteCacheWithName:
ne saisit tout simplement pas cette situation, en ce que ce que vous avez changé n'était pas la demande, le prédicat ou le descripteur de tri, mais pourrait être décrit avec plus de précision comme ayant muté le jeu de résultats pendant que la récupération était en cours.
Il m'a fallu une éternité pour retrouver ce petit morceau de trivia. J'espère que vous en bénéficierez.
Combien de classes implémentent la même méthode de résultats - (NSFetchedResultsController *), utilisez-vous un cache différent pour chacune? J'avais le même problème et je pense que je le corrige en utilisant un nom de cache différent pour certains clases car j'ai différents NSPredicates.