NSManagedObjectContext 通过通知中心问题在多个线程上保存/合并

Posted

技术标签:

【中文标题】NSManagedObjectContext 通过通知中心问题在多个线程上保存/合并【英文标题】:NSManagedObjectContext saving/merging over multiple threads through notifcation center issue 【发布时间】:2011-05-04 20:04:01 【问题描述】:

这更多的是为什么它会起作用,这不是问题......

我在多个线程上使用 CoreData。我有两个线程从主线程中产生,它们都执行类似的调用:

    id observerObject = [notificationCenter addObserverForName:NSManagedObjectContextDidSaveNotification 
                                                        object:secondManagedObjectContext 
                                                         queue:nil 
                                                    usingBlock:^(NSNotification *saveNotification) 
                                                        dispatch_async(dispatch_get_main_queue(), ^
                                                            [mainThreadManagedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];
                                                        );
                                                    ];
    [secondManagedObjectContext save:nil];


    [notificationCenter removeObserver:observerObject
                                  name:NSManagedObjectContextDidSaveNotification 
                                object:syncManagedObjectContext];

这似乎工作正常,但之前我在通知中心这样做并且遇到了一些问题:

    id observerObject = [notificationCenter addObserverForName:NSManagedObjectContextDidSaveNotification 
                                                        object:secondManagedObjectContext 
                                                         queue:[NSOperationQueue mainQueue]
                                                    usingBlock:^(NSNotification *saveNotification) 
                                                        [mainThreadManagedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];
                                                    ];

这有时会起作用,但有时 XCode 会在启动时暂停并在调用上放置一个绿色断点并仅列出线程及其编号,但没有错误。 (注意:这个问题只有在我产生了两个或更多线程时才会出现)。

罪魁祸首似乎是:[NSOperationQueue mainQueue],但我似乎无法弄清楚为什么它会使线程暂停。我能够在调试器中按 continue 并继续前进……但我不明白为什么它会以这种方式运行。

我认为我做错了什么,我担心我的新方法可能只是一个 hack。

感谢您的帮助!

【问题讨论】:

【参考方案1】:

我认为第一个工作是因为异步调度。否则,通知中心将暂停,直到任何特定通知完成。您遇到的问题听起来像是一个典型的停顿,其中代码只是暂停而没有错误,直到最终调试器超时。

【讨论】:

【参考方案2】:

不确定这是否有帮助,但如果队列为零,请尝试使用通用队列。看看苹果文档中的接待员设计模式。

 NSOperationQueue *queue = [[NSOperationQueue alloc] init];

【讨论】:

【参考方案3】:

您的第一个代码示例中的合并在主线程上正确分派,主线程很可能也是创建 moc 的线程。

在您的第二个示例中,如果通知是在 bg 线程上发出的,则合并将在后台线程上执行(通知回调始终在与发布通知的线程相同的线程上调用)。

顺便说一句,我现在宁愿使用 NSManagedObjectContext 自己的performBlock: 方法(>= ios 5),而不是使用主队列。在带有 ARC 的 iOS5 上,此代码归结为:

__weak typeof(self) weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification *note) 
    [weakSelf.moc performBlock:^
        [weakSelf.moc mergeChangesFromContextDidSaveNotification:note];
    ];
];

【讨论】:

以上是关于NSManagedObjectContext 通过通知中心问题在多个线程上保存/合并的主要内容,如果未能解决你的问题,请参考以下文章

NSManagedObjectContext 通过通知中心问题在多个线程上保存/合并

NSFetchedResultsController 错过了合并的 NSManagedObjectContext 的更新

NSManagedObjectContext insertObject - 字符串存储为空

iOS 在后台保存主线程 NSManagedObjectContext 更改

NSManagedObjectContext objectWithID 生命周期方法(派生属性)

NSIncrementalStore:从这个 NSManagedObjectContext 的协调器无法访问对象的持久存储