NSFetchedResultsController: changing predicate not working?
Asked Answered
M

4

39

I'm writing an app with two tables on one screen. The left table is a list of folders and the right table shows a list of files. When tapped on a row on the left, the right table will display the files belonging to that folder.

I'm using Core Data for storage. When the selection of folder changes, the fetch predicate of the right table's NSFetchedResultsController will change and perform a new fetch, then reload the table data. I used the following code snippet:

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];

However the fetch results are still the same. I've NSLog'ed "predicate" before and after the fetch, and they were correct with updated information. The fetch results stay the same as initial fetch (when view is loaded).

I'm not very familiar with the way Core Data fetches objects (is there a caching system?), but I've done similar things before(changing predicates, re-fetching data, and refreshing table) with single table views and everything went well.

If someone could gave me a hint I would be very appreciated.

Thanks in advance.

Mcgowan answered 20/3, 2010 at 5:46 Comment(0)
D
61

I had almost exactly this problem, until I found the hint in a very recent blog post at iphone incubator

NSFetchedResultsController is caching the first results. (You probably have something set at initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName)

I'm guessing your code (like mine) is a derivation of the CoreData sample, so assuming it's @"Root", before you change the predicate, do a

[NSFetchedResultsController deleteCacheWithName:@"Root"];  
Deannadeanne answered 22/3, 2010 at 11:21 Comment(4)
Thanks, that fixed my issue too. I didn't get the same results though, I got a crash in iOS 3.2/4.0. It worked fine in 3.1 though!Anaximenes
Note that the entity cache is preserved across application runs. I had a very confusing time trying to figure out why changing the predicate itself in the source code didn't have any effect upon rebuilding and running the app. Apple says the following: "If it finds a cache with the same name, the controller tests the cache to determine whether its contents are still valid. The controller compares the current entity name, entity version hash, sort descriptors, and section key-path with those stored in the cache". Note that the predicate is not included in that list.Pregnant
For a more portable version, you can pass in the cacheName: NSFetchedResultsController<NSFetchRequestResult>.deleteCache(withName: fetchedResultsController.cacheName) or [NSFetchedResultsController deleteCacheWithName: [fetchedResultsController cacheName]]Ornery
Works for me! Thanks!Unionize
C
3

This worked for me:

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

NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
    NSLog(@"%@, %@", error, [error userInfo]);
    abort();
} 
Catanzaro answered 18/5, 2016 at 8:45 Comment(1)
Just setting the predicate and performing the fetch again did the jobJackfish
M
2

In my case deafgreatdane's answer isn't working; what I did instead is probably naive, but works:

  • create corresponding predicate(s) in the configureCell:atIndexPath: method (called in tableView:cellForRowAtIndexPath:)
  • then call:
    [_fetchedResultsController.fetchRequest setPredicate:predicate];
    [_fetchedResultsController performFetch:nil];
  • refer to the returned object by calling [self.fetchedResultsController objectAtIndexPath:indexPath]
Menticide answered 2/11, 2015 at 17:16 Comment(0)
C
2

Had a similar issue in my swift project. This worked for me

NSFetchedResultsController.deleteCache(withName: fetchedResultsController.cacheName)

Cenotaph answered 28/9, 2018 at 18:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.