问题
I have nearly tried everything but cannot figure out what is wrong. I have a NSFetchedResultsController and fetch some posts out of core data. Then I have a method where I insert new posts into the same context and save the context. Normally, the didChangeObject: method should be called now, but it does not. I have a similar view controller where I do basically the same on a different table (=nsmanaged object) and there the didChangeObject: method gets called successfully.
What I have tried so far:
Created another context just for this view controller
Removed the cache of the NSFetchedResultsController
The following method fetches the data out of the core data db and 'stores' it into the NSFetchedResultsController (variable: controller).
//reloading newsgroups from coredata
- (void)reloadNewsgroupsFromCoreData
{
//creating fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"];
//sorting by transient date (hour and secons cutted off)
NSSortDescriptor *sortByDate = [[NSSortDescriptor alloc] initWithKey:@"dateCreatedTransient" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByDate, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
//where clause
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"ref_subscribed_newsgroup == %@ AND references == nil", self.newsgroup]];
//setting fetchrequest
self.controller = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:self.context
sectionNameKeyPath:@"dateCreatedForSections"
cacheName:nil]; //todo, maybe add a cache here!
//fetch
NSError *error;
[self.controller performFetch:&error];
if (error) {
NSLog(@"%@", error);
}
}
Furthermore, according to the documentation I set the delegate of the NSFetchedResultsController to my view controller (this is the same where the aforementioned fetch method is located).
In viewDidLoad:
self.controller.delegate = self;
Then I have implemented the methods from the protocol, also the didChangeObject:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
// I HAVE ADDED A BREAKPOINT HERE BUT IT NEVER STOPS HERE.
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath]
atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray
arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray
arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
Then I have another method that stores some posts into core data. I think this is important: This method is invoked via a delegate from another thread. (The server connection invokes it using performSelectorOnMainThread:...)
- (void)storeIntoCoreData:(NSArray*)postsArray
{
...
Post *entity = [NSEntityDescription insertNewObjectForEntityForName: @"Post" inManagedObjectContext:context];
entity.inReply = dummy.in_reply;
entity.body = dummy.body;
entity.email = dummy.email;
entity.from = dummy.from;
entity.messageIdentifier = dummy.message_identifier;
entity.references = dummy.references;
entity.subject = dummy.subject;
entity.dateCreated = dummy.date;
entity.unread = [NSNumber numberWithInt:1];
...
[self.context save:&error];
if (error)
{
NSLog(@"error: %@", error);
}
// IMPORTANT: CURRENTLY I AM CALLING THIS METHOD AGAIN HERE, WHICH
// FETCHES ALL POSTS OUT OF CORE DATA.
// THIS IS SO UGLY AND NOT PERFORMANT.
// THEN I INVOKE RELOADDATA ON THE TABLEVIEW TO RELOAD THE ENTIRE TABLE
// BUT THERE WAS JUST ONE INSERT SO A ENTIRE RELOAD WOULD NOT BE NECESSARY.
[self reloadNewsgroupsFromCoreData];
[self.tableView reloadData];
// I HAVE TO DO THIS BECAUSE THE didChangeObject METHOD GETS NOT CALLED.
}
Does anyone have a hint or a suggestion what could be wrong?
Thanks and regards, Chris
回答1:
The problem is that you're setting the controller delegate in viewDidLoad and then later allocating a new controller in reloadNewsgroupsFromCoreData. Your newly allocated controller doesn't have the delegate set. Try setting the delegate directly in reloadNewsgroupsFromCoreData.
You typically don't want to allocate a new NSFetchedResultsController whenever something changes in your data. The entire point of using NSFetchedResultsController is to get delegate messages via NSFetchedResultsControllerDelegate when something changes. You only need to allocate a new NSFetchedResultsController if your fetch request changes. I suggest having another look at the Apple Docs.
来源:https://stackoverflow.com/questions/10894137/didchangeobject-not-called-of-nsfetchedresultscontroller