NSManagedObject:在单独的线程上创建

Posted

技术标签:

【中文标题】NSManagedObject:在单独的线程上创建【英文标题】:NSManagedObject: create on separate thread 【发布时间】:2011-07-07 17:09:54 【问题描述】:

我了解 Core Data 不是线程安全的,并且与上下文关联的 NSManagedObjectContext 和 NSManagedObjects 不能在线程之间传递。

问题:

但是,如果我的主线程上有一个 NSManagedObjectContext,我可以在后台线程上创建一个 NSManagedObject 对象吗(不将它附加到任何上下文——也就是说,只需在 NSManagedObject 上调用 alloc/init),然后传递那个 NSManagedObject返回主线程并从那里将其添加到上下文中?我查看了有关 Core Data concurrency 的文档,但找不到任何说明这种使用模式可以的内容。

上下文:

我有一个执行复杂任务然后发布结果的后台线程。结果是一个包含几个属性的 NSManagedObject 子类:时间、文件路径和成功或错误消息(作为字符串)。我想在后台线程上创建结果对象,然后将其扔回主线程并将其添加到将在 tableView 中显示的 Core Data 上下文中。

如果我不能在后台线程上创建 managedObject,那么我需要创建一个字典,将字典传递给主线程,读取键,从这些值创建 managedObject,等等。看起来更干净如果可能,在后台线程上创建 managedObject。

【问题讨论】:

【参考方案1】:

更好的方法是每个线程都有一个上下文。这样每个线程都会有自己的便笺簿来玩。然后,当您的后台线程完成时,告诉您的主线程更新其视图或 ui 表视图或您如何呈现数据。

您需要在发生更改时通知您的主线程。最大的问题是,不同线程和主线程之间的上下文不知道彼此。核心数据中有一种方法可以使上下文保持同步。当你想保存时,后台线程上的上下文应该广播一个 NSManagedObjectContextDidSaveNotification 通知。

例如,在你的 NSOperation 的 main 方法中,你可以这样做:

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
[nc addObserver:self
       selector:@selector(mergeChanges:)
           name:NSManagedObjectContextDidSaveNotification
         object:context];

mergeChanges 将是您的 NSOperation 实例中的私有方法。

合并更改示例

- (void)mergeChanges:(NSNotification *)notification

    ApplicationController *appController = [[NSApplication sharedApplication] delegate];
    NSManagedObjectContext *mainContext = [appController managedObjectContext];

    // Merge changes into the main context on the main thread
    [mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                                  withObject:notification
                               waitUntilDone:YES];  

【讨论】:

@Doug 是的,我知道如何在多线程环境中使用 Core Data。我的问题是我可以在任何线程上分配/初始化一个 NSManagedObject,然后将它添加到与主线程关联的上下文中吗?换句话说,如果我在不使用 -insertNewObjectForEntityForName:InManagedObjectContext: 的情况下创建 NSManagedObject,我可以在主线程上使用 NSManagedContext 的 addObject: 方法在后台线程上添加 managedObject alloc/init-ed 吗?与上述方法相关的背景上下文的额外开销对于大型、复杂的对象图来说是相当大的。 虽然init会创建一个NSManagedObject,但它处于无效状态。 Objective-C 不强制使用指定的初始值设定项,但如果您希望对象处于有效状态,则无论如何都必须使用它们。对于 NSManagedObject 的实例,指定的初始化程序是 '-insertNewObjectForEntityForName:InManagedObjectContext:'

以上是关于NSManagedObject:在单独的线程上创建的主要内容,如果未能解决你的问题,请参考以下文章

我无法使用非主 MOC 在后台线程上创建 NSManagedObject 的新实例

如何在多个线程上处理 NSManagedObjectContext 和 NSManagedObject 创建和编辑?

跨线程传递临时 NSManagedObject

将 NSManagedObject(在主上下文中创建)从后台线程传递到主线程是不是安全?

Xcode NSManagedObject 子类自动生成以覆盖单独组中的现有文件

正确关闭使用 ATL 在单独线程上创建的窗口