主线程上的NSFetchedResultsController忽略从另一个线程保存到Core Data?

joh*_*ham 3 multithreading core-data nsfetchedresultscontroller nsoperationqueue nsmanagedobjectcontext

我有一个NSFetchedResultsController主线程.同样从主线程,我异步发送JSON的网络请求.当JSON字符串返回时,我启动NSOperation一个新的(后台)NSManagedObjectContext,解析JSON字符串,创建/更新NSManagedObject,并将它们保存在上下文中.后台上下文与主上下文具有相同的persistentStore.有了这个,我有两个问题:

  1. 我认为从任何上下文(在任何线程上)对持久性存储的任何保存都会通知主要NSFetchedResultsController有变化,但到目前为止它没有发现任何变化.我应该做些什么来通知主线程NSFetchedResultsController有外部save的,以便相应的tableView更新?

  2. 因此,在主线程上,我订阅NSManagedObjectContextWillSaveNotification并正确查看所有上下文(包括完全在单独线程上存在的上下文)何时执行save操作.的苹果文档说的是notification.userInfo具有应3个阵列,一个阵列的每个在后台线程的"更新,删除和插入的"模型对象的字典.但是,这对我userInfo来说总是如此nil.我有什么想法我做错了吗?

订阅NSManagedObjectContextWillSaveNotificationAppDelegate:

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(managedObjectContextDidSave:)
                                             name:NSManagedObjectContextWillSaveNotification 
                                           object:nil];
Run Code Online (Sandbox Code Playgroud)

以及在AppDelegate中保存上下文的方法:

- (void)managedObjectContextDidSave:(NSNotification *)notification {
    DLog(@"notification: %@", notification); //not nil
    DLog(@"notification user info: %@", notification.userInfo); // always nil... why??

    NSManagedObjectContext *theContext = notification.object;
    if(theContext != context) {
        DLog(@"---- SAVED ON ANOTHER CONTEXT");

        // should I notify NSFetchedResultsController that there were context saves on background threads?
        // how can I merge contexts if userInfo is nil?
    }
}
Run Code Online (Sandbox Code Playgroud)

我还想知道处理多个线程(使用单独的NSManagedObjectContexts)和Core Data的最佳实践.

Nic*_*idt 5

您观察到错误的通知:您需要观察的通知的名称是NSManagedObjectContextDidSaveNotification(不是NSManagedObjectContextWillSaveNotification).

  • 控制器依赖于主上下文,因此执行此操作的正确方法(实际上唯一的方法)是将更改合并到该上下文中. (3认同)
  • 是的,您应该使用` - [NSManagedObjectContext mergeChangesFromContextDidSaveNotification:]来告诉主要上下文合并更改.如果`NSFetchedResultController`有一个委托,它将自动刷新它的内容并通知对其委托的更改.否则,您可以通过发送`performFetch:`重新加载内容. (2认同)