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 的指针
NSManagedObjectContext: performBlockAndWait vs performBlock 通知中心