Reputation: 689
My iPhone (4.1.2) app has a menu, each of whose entries lead to a different table view populated by NSManagedObject
subclasses. I use the same view controller for each, but what is different is the fetch request's predicate, so different data is displayed depending on which menu item the user chose. Simple enough.
Everything works fine before I actually save the managed object context. However, things go weird after the app enters the background and reenters the foreground, because I'm using this:
- (void)applicationDidEnterBackground:(UIApplication*)application {
NSError *error = nil;
if(managedObjectContext != nil)
if([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
I figured this would be an appropriate time to save my data. But after this has happened, after I call performFetch:
on my fetched results controller, its fetchedObjects
are the fetched objects from the PREVIOUS fetch request, and not the new one. That is, if I do:
// Choose menu item 1
[self.fetchedResultsController performFetch:nil]; // With fetch request 1
NSLog(@"%i objects were fetched", [[self.fetchedResultsController fetchedObjects] count]); // Items for fetch request 1
// Go back to menu, choose menu item 2 for new fetch request
[self.fetchedResultsController performFetch:nil]; // Fetch request 2
NSLog(@"%i objects were fetched", [[self.fetchedResultsController fetchedObjects] count]); // Items for Fetch request 2
// Hit home button, applicationDidEnterBackground: is called
// Relaunch
// Choose menu item 1
[self.fetchedResultsController performFetch:nil]; // With fetch request 1
NSLog(@"%i objects were fetched", [[self.fetchedResultsController fetchedObjects] count]); // Items for fetch request 2 - HUH?
So the issue is with calling save:
on my managed object context. If I never save data, the fetch requests never get mixed up like this, but once I do, it's like old fetch requests are being saved, even though the fetchedResultsController
itself is only created at my view controller's viewDidLoad
method.
Anyone have any idea what's going on?
UPDATE: More code.
- (void)viewDidLoad {
delegate = (MAAppDelegate *)[[UIApplication sharedApplication] delegate];
managedObjectContext = delegate.managedObjectContext;
[self.fetchedResultsController performFetch:nil];
NSUInteger count = [[self.fetchedResultsController fetchedObjects] count]; // Bug is detected here
// ...
}
- (NSFetchedResultsController *)fetchedResultsController {
if(_fetchedResultsController)
return _fetchedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tweet" inManagedObjectContext:managedObjectContext];
NSPredicate *predicate = nil;
if([self.navigationItem.title isEqualToString:@"Personal"])
predicate = [NSPredicate predicateWithFormat:@"account.username = %@ AND user.username = %@", delegate.currentAccount.username, delegate.currentAccount.username];
else if([self.navigationItem.title isEqualToString:@"Favorites"])
predicate = [NSPredicate predicateWithFormat:@"account.username = %@ AND favorited = YES", delegate.currentAccount.username];
else
predicate = [NSPredicate predicateWithFormat:@"account.username = %@", delegate.currentAccount.username];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"tweetID" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:@"retrieved"
cacheName:@"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return _fetchedResultsController;
}
Upvotes: 1
Views: 736
Reputation: 25429
It's hard to tell without seeing additional code, but the problem you are experiencing is probably due to the initial lines in your fetchedResultsController
method:
if(_fetchedResultsController)
return _fetchedResultsController;
What is happening is that - just a guess - you are reusing the previous _fetchedResultsController
which has been setup using the predicate for fetch request 2. That is, in your viewDidLoad
method the line
[self.fetchedResultsController performFetch:nil];
is not instantiating a new NSFetchedResultsController
as you think: the previous one is returned immediately when invoking fetchedResultsController
, owing to the initial two lines.
Upvotes: 1
Reputation: 13257
Are you caching in each subview and, if you are, are you using a different name for each cache?
Upvotes: 1