NSManagedObjectContext的performBlock:用于什么?

68
在iOS 5中,NSManagedObjectContext新增了两个方法performBlock:performBlockAndWait:。这些方法实际上是用来做什么的?它们在旧版本中替换了什么?应该传递哪种类型的块?我如何决定使用哪个方法?如果有人有这些方法的用法示例,那就太好了。

你是不是想说“NSManagedObjectContext”? - MikeG
我非常确定他这样做了。也许 Nevan 可以在 http://stackoverflow.com/tags/nsmanagedobjectcomplex/synonyms 上建议这个。 - Bjinse
修正了拼写错误,感谢提醒。 - nevan king
2个回答

126
方法performBlock:performBlockAndWait:用于向您的NSManagedObjectContext实例发送消息,如果MOC使用NSPrivateQueueConcurrencyTypeNSMainQueueConcurrencyType进行初始化,则需要在块中执行任何与这些上下文类型相关的操作,例如设置持久存储或保存更改。

performBlock:将块添加到后备队列并安排在其自己的线程上运行。该块将立即返回。您可能会将其用于长时间的持久化操作。

performBlockAndWait:也会将块添加到后备队列并安排在其自己的线程上运行。但是,该块将一直等待,直到块执行完成为止。如果您需要知道操作是否成功才能继续进行,则可以选择此选项。

例如:

__block NSError *error = nil;
[context performBlockAndWait:^{
    myManagedData.field = @"Hello";
    [context save:&error];
}];

if (error) {
    // handle the error.
}

请注意,因为我使用了performBlockAndWait:,所以我可以在块外访问错误。使用performBlock:需要不同的方法。
来自iOS 5核心数据发布说明
NSManagedObjectContext现在提供了结构化的并发操作支持。使用initWithConcurrencyType:创建托管对象上下文时,您有三个选项可用于其线程(队列)关联:
- 限制型(NSConfinementConcurrencyType)。
这是默认值。您保证上下文不会被除创建它的线程之外的任何线程使用。(这与之前发布版本中使用的完全相同的线程要求相同。)
- 私有队列(NSPrivateQueueConcurrencyType)。
上下文创建和管理一个私有队列。上下文拥有队列并为您管理所有细节(前提是您使用如下所述的基于块的方法)。
- 主队列(NSMainQueueConcurrencyType)。
上下文与主队列相关联,并因此与应用程序的事件循环联系在一起,但否则类似于基于私有队列的上下文。您使用此队列类型来链接到控制器和UI对象的上下文,这些对象仅需要在主线程上使用。

2
@MikeG 我认为你可能把事情搞反了(或者我在阅读时反了)。performBlockAndWait将会阻塞调用它的任何线程 - 主线程或其他线程 - 并且不关心MOC与哪个线程相关。还是我理解错了? - RonLugge
1
我需要在performBlock中创建ManagedObject吗? - thierryb
据我所知,performBlockAndWait 在调用者的线程上运行。 - Bradley Thomas
有人能解释一下“块在执行完成之前不会返回”的意思吗? - marciokoko
@MikeG 我不确定,我应该将所有实体修改都包装在 performBlock 中,还是只在保存部分包装? - Maen
显示剩余9条评论

-4

它们允许您在多个线程中访问相同的managedObjectContext

我不确定我是否正确,但这是我的使用方法。

如果您只在一个线程上执行managedObjectContext,则无需使用performBlockAndWait。如果您在多个线程上执行它,则需要使用performBlock

所以,如果您在主线程上,对于主要的managedObjectContext,您不需要执行performBlockAndWait。至少我没有,并且运行良好。

但是,如果您在其他线程上访问该managedObjectContext,那么您需要执行performBlockAndWait

这就是performBlockperformBlockAndWait的目的。

如果我在这里有错误,请有人纠正我。当然,如果您只在一个线程上访问上下文,那么可以简单地使用默认设置。


@FábioOliveira 不行 - Apple 对此非常明确:你不能跨线程访问它们。PerformBlock 允许您让一个线程请求另一个线程为其执行代码。编译器将允许您进行简单的访问,但如果您这样做,您保证迟早会出现运行时一致性错误(即:损坏的 CoreData 数据库,所有地狱就会爆发。我曾经历过,看到过)。 - Adam
据我所知,performBlockAndWait 在调用者的线程上运行,而不像 performBlock。 - Bradley Thomas
2
@BradThomas performBlockAndWait: 在上下文线程上运行,就像performBlock:一样,但它会让调用者的线程等待块执行完成。 - tonytony
1
@tonytony,我想澄清一下,所以我向你提出挑战...你所说的与此主题发布的令人信服的最佳答案(和令人信服的问题)不符...https://dev59.com/gmgt5IYBdhLWcg3wxANj - Bradley Thomas
1
@BradThomas 我在 performBlockAndWait: 调用内外尝试使用调试器执行 po [NSThread currentThread],结果发现它确实在 调用者 线程上运行。感谢提供的链接。 - tonytony
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接