47 votes

NSFetchedResultsController s'écraser sur performFetch: lors de l'utilisation d'un cache

- Je faire usage de NSFetchedResultsController pour afficher un ensemble d'objets, qui sont sectionnés à l'aide de dates. Sur 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 redémarrée, je reçois un crash. - Je spécifier un cache lors de l'initialisation de la NSFetchedResultsController, et quand je n'en ai pas, il fonctionne parfaitement.

Voici comment j'ai créer 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;
}

Ce sont les messages que je reçois quand 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 pas la moindre idée de pourquoi c'est à dire, que je ne crois pas que je suis en train de faire quelque chose de spécial qui serait à l'origine. Le seul problème potentiel est la section de l'en-tête (jour), que j'construire comme cela 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 très bien si il n'y a pas de cache en cause. Toute aide appréciée!

65voto

IssamTP Points 1256

J'ai eu un problème similaire avec une de mes applications, lorsque Apple a publié une nouvelle iOS 4.0. Recherche:

fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[self managedObjectContext] sectionNameKeyPath:nil cacheName:nil];

Et de définir la valeur du paramètre cacheName à néant. Il a travaillé pour moi, j'espère qu'elle sera pour vous. Laissez-moi savoir.

30voto

Mike V Points 266

J'ai commencé à faire la même erreur quand j'ai mis à jour par MacBook Pro pour Snow Leopard 10.6.4 et le dernier SDK.

Comme il s'avère, beaucoup d'entre nous ont été à l'aide de code qui n'était pas en conformité avec les règles, mais nous n'avons pas le savoir parce que CoreData n'était pas vraiment de se comporter conformément à ses propres règles.

Plus précisément, lorsque vous chercher les choses, ils s'en cache, et dans la version 4.0, qui cache n'est pas supprimé automatiquement dans les cas où il a été purgée dans la première SDK.

Pour moi, la solution a été simple. J'ai juste utilisé la méthode de la classe qui vide les caches. Vous pouvez spécifier une personne physique, mais j'ai spécifié le néant jusqu'à ce qu'il leur fait tout dans ce morceau de code:

[NSFetchedResultsController deleteCacheWithName:nil];

Soudain, la petite application que je ai travaillé uniquement pour me familiariser avec CoreData fonctionne à nouveau.

15voto

Mark Adams Points 17189

Directement à partir de la documentation pour NSFetchedResultsController:

La modification de la Demande de récupération

Vous ne pouvez pas simplement changer de demande de récupération pour modifier les résultats. Si vous souhaitez modifier la demande de récupération, vous doit:

  1. Si vous utilisez un cache, supprimer (à l'aide d' deleteCacheWithName:). En général, vous ne devriez pas utiliser un cache si vous modifiez le chercher demande.

  2. Changement de la demande de récupération.

  3. Invoquer performFetch:.

6voto

Terrence Tan Points 244

J'ai rencontré un problème similaire. Quand j'ai inspecté le Débogueur de la Console, il a montré que la mise en cache des objets et les objets ont été récupérés afin que je puisse comprendre pourquoi ils sont incompatibles. Dans mon cas, c'était dû à un autre prédicat.

Puisque les valeurs dans mon prédicat ne sont pas dynamiques, je pourrais spécifier un autre nom de cache pour chaque prédicat. Qui permettra de créer un cache pour chaque "type" je précise.

Je suppose que vous devez évaluer votre besoin d'avoir la mémoire cache. Pour spécifier néant, signifie que l'extraction est effectuée lors de chaque appel.

J'ai compris que l'erreur se produit uniquement lorsque l'extraire la demande de certains changements. Si vous êtes à la création d'un nouveau NSFetchRequest OU de changer le prédicat OU de tri de descripteur, vous devez supprimer le cache ou l'utilisation d'un cache différent. Sinon, vérifiez que vous avez le même NSFetchRequest ou assurez-vous que votre NSFetchedResultsController est conservé et ce qui devrait résoudre votre problème.

3voto

shosti Points 4672

Si vous utilisez le simulateur, essayez de le réinitialiser--je suppose que vous avez changé votre entité de la carte et de se confondre par un reste de cache. Si non, vous pouvez essayer de faire ce que le message d'erreur indique:

- (void)applicationWillTerminate:(UIApplication *)application {
    [NSFetchedResultsController deleteCacheNamed:@"Events"];
    //etc
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X