主线程上的 NSFetchedResultsController 忽略从不同线程保存到核心数据?

Posted

技术标签:

【中文标题】主线程上的 NSFetchedResultsController 忽略从不同线程保存到核心数据?【英文标题】:NSFetchedResultsController on main thread ignoring saves to Core Data from a different thread? 【发布时间】:2011-12-22 19:02:23 【问题描述】:

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

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

    所以,在主线程上,我订阅了NSManagedObjectContextWillSaveNotification,并正确地看到所有上下文(包括完全存在于单独线程上的上下文)何时执行save 操作。 apple docs 说 notification.userInfo 应该有一个包含 3 个数组的字典,一个数组用于后台线程上的每个“更新、删除和插入”模型对象。但是,userInfo 对我来说始终是 nil。任何想法我做错了什么?

订阅 AppDelegate 中的NSManagedObjectContextWillSaveNotification

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(managedObjectContextDidSave:)
                                             name:NSManagedObjectContextWillSaveNotification 
                                           object:nil];

以及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?
    

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

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

以上是关于主线程上的 NSFetchedResultsController 忽略从不同线程保存到核心数据?的主要内容,如果未能解决你的问题,请参考以下文章

主线程异常上的android os网络

在后台线程上创建一个视图,将其添加到主线程上的主视图

在后台创建的 NSManagedObject 变成了主线程上的错误

无法访问主线程上的数据库 - Android Room - 使用 ThreadPoolExecutor

XMLHTTPRequest 错误:不推荐使用主线程上的同步 XMLHttpRequest ...(SoundCloud API)

“无法访问主线程上的数据库,因为它可能会长时间锁定 UI。”我的协程错误