CoreData 的 performBlock: 和故障

Posted

技术标签:

【中文标题】CoreData 的 performBlock: 和故障【英文标题】:CoreData's performBlock: and faulting 【发布时间】:2013-11-12 09:24:40 【问题描述】:

我正在使用 performBlock: 和 performBlockAndWait: 方法在只读数据库上的上下文中执行获取请求(它与我的应用程序一起打包,因此从未写入)。

我是否也应该将每个 NSManagedObject 访问器包装在 performBlockAndWait: 中? - 那会很混乱。目前,每当 CoreData 的一对多关系出现故障而 CoreData 的私有队列正在使用 performBlock 执行时,我都会崩溃:

类似:

NSManagedObject* alreadyFetchedObject = ...;
NSArray* alreadyFetchedObject.otherObjects; // Crashes here on main thread (no performBlock wrapped around accessing otherObjects)

.

[context performBlockAndWait:^
    // Currently executing here on CoreData's own queue
    result = [context executeFetchRequest:fetchRequest error:nil];
];

【问题讨论】:

【参考方案1】:

是的,当然。也许与已关联到在主线程上执行的上下文相关联的托管对象除外。但为了清楚起见,我总是将访问包装到performBlock:。小心performBlockAndWait: - 这很容易导致死锁。

另外,当你有这样的陈述时:

NSManagedObject* alreadyFetchedObject = ...;

之后访问alreadyFetchedObject,需要确保对应的托管对象上下文依然存在。因此,总是使用performBlock:performBlockAndWait: 访问托管对象会提醒您不要意外删除上下文;)

【讨论】:

好的,谢谢,太糟糕了,因为它看起来非常丑陋,几乎所有东西都执行块:( 当您知道并且要求您的上下文与主线程相关联时,您可以放心地放松这一点:例如,当初始化表格中的单元格时查看,例如:User* user = [self.userModels objectAtIndex:0];。这里,self.userModels 是一个托管对象数组,仅用于在主线程中处理,用于在表格视图中显示它。然后在这种情况下,使用performBlockAndWait: 将是多余的,而且无论如何都没有必要,因为如果它不是主线程,那么您无论如何都无法显示用户。 我的真实示例是在不同的线程上搜索,然后在表格中显示主线程上的数据,然后在选择时显示更多信息。单元格标题之类的预取内容可以正常工作,但其他内容是问题所在。我想当它被点击时我可以通过它的托管对象ID在主线程上再次获取它(这几乎是唯一单独的数据库线程进程) 注意:您不能在不同的线程 B 中使用来自线程 A 的托管对象。请阅读:Concurrency with Core Data 中的 使用通知跟踪其他线程中的更改。因此,当您说需要使用相关上下文重新获取这些托管对象时,您是对的。 当我说线程时,我的意思是 coredata 在您使用 performBlock 时在后台使用的线程: - 也是只读的,因此无需更改跟踪

以上是关于CoreData 的 performBlock: 和故障的主要内容,如果未能解决你的问题,请参考以下文章

CoreData 和 NSManagedObject 上下文 - 私有与主

CoreData multithreading_violation 调试

指向 performBlock 之外的 NSManagedObject 的指针

NSThread gtm_performBlock 错误

NSManagedObjectContext: performBlockAndWait vs performBlock 通知中心

在 performBlock 中分配时 NSManagedObjectContext nil