39 votes

NSFetchedResultsController : la modification du prédicat ne fonctionne pas ?

J'écris une application avec deux tableaux sur un seul écran. Le tableau de gauche est une liste de dossiers et le tableau de droite montre une liste de fichiers. Lorsque l'on tape sur une ligne à gauche, le tableau de droite affiche les fichiers appartenant à ce dossier.

J'utilise Core Data pour le stockage. Lorsque la sélection du dossier change, le prédicat de récupération du NSFetchedResultsController de la table de droite change et effectue une nouvelle récupération, puis recharge les données de la table. J'ai utilisé l'extrait de code suivant :

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"list = %@",self.list];
[fetchedResultsController.fetchRequest setPredicate:predicate];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {   
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}
[table reloadData];

Cependant, les résultats de la recherche sont toujours les mêmes. . J'ai vérifié NSLog'ed "predicate" avant et après la récupération, et ils étaient corrects avec les informations mises à jour. Les résultats de la recherche restent les mêmes que ceux de la recherche initiale (lorsque la vue est chargée).

Je ne connais pas très bien la façon dont Core Data récupère les objets (y a-t-il un système de mise en cache ?), mais j'ai déjà fait des choses similaires (modification des prédicats, nouvelle récupération des données et rafraîchissement de la table) avec des vues de table unique et tout s'est bien passé.

Si quelqu'un pouvait me donner un indice, je lui en serais très reconnaissant.

Merci d'avance.

62voto

deafgreatdane Points 816

J'avais presque exactement le même problème, jusqu'à ce que je trouve la solution dans un article de blog très récent à l'adresse suivante incubateur pour iphone

NSFetchedResultsController met en cache les premiers résultats. (Vous avez probablement défini quelque chose à initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName)

Je suppose que votre code (comme le mien) est une dérivation de l'échantillon CoreData, donc en supposant que c'est @"Root", avant de changer le prédicat, faites un

[NSFetchedResultsController deleteCacheWithName:@"Root"];

0 votes

Merci, ça a réglé mon problème aussi. Je n'ai pas obtenu les mêmes résultats cependant, j'ai eu un crash dans iOS 3.2/4.0. Cela a bien fonctionné en 3.1 !

1 votes

Notez que le cache de l'entité est préservé entre les différentes applications . J'ai eu beaucoup de mal à comprendre pourquoi la modification du prédicat lui-même dans le code source n'avait aucun effet sur la reconstruction et l'exécution de l'application. Apple dit ce qui suit : "S'il trouve un cache portant le même nom, le contrôleur teste le cache pour déterminer si son contenu est toujours valide. Le contrôleur compare le nom actuel de l'entité, le hachage de la version de l'entité, les descripteurs de tri et le chemin clé de la section avec ceux stockés dans le cache". Notez que le prédicat est non inclus dans cette liste.

0 votes

Pour une version plus portable, vous pouvez passer dans l'option cacheName : NSFetchedResultsController<NSFetchRequestResult>.deleteCache‌​(withName: fetchedResultsController.cacheName) o [NSFetchedResultsController deleteCacheWithName: [fetchedResultsController cacheName]]

6voto

mmalc Points 7663

Ce point est abordé dans la documentation aquí (voir Modifier la demande d'extraction).

3voto

NSPratik Points 2728

Cela a marché pour moi :

[NSFetchedResultsController deleteCacheWithName:nil];  
[self.fetchedResultsController.fetchRequest setPredicate:predicate]; 

NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
    NSLog(@"%@, %@", error, [error userInfo]);
    abort();
}

2voto

dobranoc Points 253

Dans mon cas, la réponse de deafgreatdane ne fonctionne pas ; ce que j'ai fait à la place est probablement naïf, mais fonctionne :

  • créer le ou les prédicats correspondants dans le configureCell:atIndexPath: (appelée dans tableView:cellForRowAtIndexPath: )

  • alors appelez :
    [_fetchedResultsController.fetchRequest setPredicate:predicate];
    [_fetchedResultsController performFetch:nil];

  • faire référence à l'objet retourné en appelant [self.fetchedResultsController objectAtIndexPath:indexPath]

2voto

lionserdar Points 1121

J'ai eu un problème similaire dans mon projet Swift. Ceci a fonctionné pour moi

NSFetchedResultsController.deleteCache(withName: fetchedResultsController.cacheName)

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