Multithreading 主线程上的NSFetchedResultsController是否忽略从其他线程保存到核心数据?

Multithreading 主线程上的NSFetchedResultsController是否忽略从其他线程保存到核心数据?,multithreading,core-data,nsfetchedresultscontroller,nsmanagedobjectcontext,nsoperationqueue,Multithreading,Core Data,Nsfetchedresultscontroller,Nsmanagedobjectcontext,Nsoperationqueue,我在主线程上有一个NSFetchedResultsController。同样从主线程,我异步发送一个JSON的网络请求。当该JSON字符串返回时,我启动一个NSOperation,该操作初始化一个新的(后台)NSManagedObjectContext,解析JSON字符串,创建/更新NSManagedObject,并将它们保存在上下文中。背景上下文与主上下文具有相同的persistentStore。关于这一点,我有两个问题: 我认为从任何上下文(在任何线程上)保存到持久性存储的任何内容都会通知主

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

  • 我认为从任何上下文(在任何线程上)保存到持久性存储的任何内容都会通知主
    nsfetchedresultscoontroller
    有更改,但到目前为止,它没有收到任何更改。我是否应该做些什么来通知主线程的
    NSFetchedResultsController
    存在外部
    save
    ,以便
    tableView
    相应地更新

  • 因此,在主线程上,我订阅了
    NSManagedObjectContextWillSaveNotification
    ,并正确查看所有上下文(包括完全存在于单独线程上的上下文)何时执行
    保存操作。他们说,
    notification.userInfo
    应该有一个包含3个数组的字典,一个数组用于后台线程上的“更新、删除和插入”模型对象。但是,对我来说,
    userInfo
    总是
    nil
    。知道我做错了什么吗

  • 订阅AppDelegate中的NSManagedObjectContextWillSaveNotification

    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(managedObjectContextDidSave:)
                                                 name:NSManagedObjectContextWillSaveNotification 
                                               object:nil];
    
    - (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?
        }
    }
    
    以及在AppDelegate中保存上下文的方法:

    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(managedObjectContextDidSave:)
                                                 name:NSManagedObjectContextWillSaveNotification 
                                               object:nil];
    
    - (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?
        }
    }
    

    我还想知道处理多线程(使用单独的NSManagedObjectContext)和核心数据的最佳做法。

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

    太好了!userInfo现在已填充了正确的词典。将更改通知
    NSFetchedResultsController
    怎么样?您建议我将这些更改合并到主上下文中,还是有更简单的方法更新
    NSFetchedResultsController
    ?控制器依赖于主上下文,因此正确的方法(实际上是唯一的方法)要做到这一点,需要将更改合并到该上下文中。是的,您应该告诉主上下文使用
    -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:
    合并更改。如果
    NSFetchedResultController
    具有委托,它将自动刷新其内容并通知对其委托所做的更改。否则,您可以通过发送
    performFetch:
    重新加载内容。