didChangeObject:未调用NSFetchedResultsController

我几乎尝试了一切,但无法弄清楚出了什么问题。 我有一个NSFetchedResultsController并从核心数据中获取一些post。 然后我有一个方法,我将新post插入到相同的上下文中并保存上下文。 通常,应该立即调用didChangeObject:方法,但事实并非如此。 我有一个类似的视图控制器,我在不同的表(= nsmanaged对象)上基本相同,并成功调用didChangeObject:方法。

到目前为止我尝试了什么:

  • 为此视图控制器创建了另一个上下文

  • 删除了NSFetchedResultsController的缓存

以下方法从核心数据db中取出数据并将其“存储”到NSFetchedResultsController(变量: 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); } } 

此外,根据文档,我将NSFetchedResultsController的委托设置为我的视图控制器(这与上述获取方法所在的位置相同)。

viewDidLoad

 self.controller.delegate = self; 

然后我已经实现了协议中的方法,以及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; } } 

然后我有另一种方法将一些post存储到核心数据中。 我认为这很重要:此方法是通过另一个线程的委托调用的。 (服务器连接使用performSelectorOnMainThread:...调用它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. } 

有没有人有暗示或建议什么可能是错的?

谢谢和问候,克里斯

问题是您在viewDidLoad设置控制器委托,然后在reloadNewsgroupsFromCoreData分配新控制器。 您新分配的控制器没有设置委托。 尝试直接在reloadNewsgroupsFromCoreData设置委托。

通常,只要数据发生变化,您就不希望分配新的NSFetchedResultsController 。 使用NSFetchedResultsController的全部目的是在更改内容时通过NSFetchedResultsControllerDelegate获取委托消息。 如果获取请求发生更改,则只需要分配新的NSFetchedResultsController 。 我建议再看一下Apple Docs 。