1. 关于__Multithreading_Violation_AllThatIsLeftToUsIsHonor__
例外:
这个线程中有详细的讨论:
CoreData 异步获取导致并发调试器错误 https://stackoverflow.com/questions/31728425/coredata-asynchronous-fetch-causes-concurrency-debugger-error
一致认为这是 CoreData 中的一个错误。
有一个错误报告:https://openradar.appspot.com/30692722 https://openradar.appspot.com/30692722截至撰写本文时,该网站已经 8 年后仍然开放。
2.如何正确使用NSAsynchronousFetchRequest
该 API 于 2014 年推出,并在 WWDC 视频中进行了讨论225_sd_whats_new_in_core_data https://devstreaming-cdn.apple.com/videos/wwdc/2014/225xxgzhqylosff/225/225_hd_whats_new_in_core_data.mov?dl=1.
没有提到是否NSAsynchronousFetchRequest
应该在主(视图)上下文或后台上下文上使用。
我使用以下命令查看了几个随机实现NSAsynchronousFetchRequest
在 GitHub 上,我找到了主要上下文和背景上下文的示例。
一件事你must do然而,当使用后台上下文时,将提取执行包装在perform
block (文档 https://developer.apple.com/documentation/coredata/using_core_data_in_the_background).
在您链接的文章和上面摘录的示例中,缺少此内容!
它应该是这样的:
privateManagedObjectContext.perform {
do {
try privateManagedObjectContext.execute(asynchronousFetchRequest)
} catch let error {
print("error trying to fetch saving objects:", error.localizedDescription)
}
}
同一篇文章还有另一个潜在问题,因此请持保留态度:
DispatchQueue.main.async {
// here the objects in result (belongs to private context) are
// accessed on the main queue – the whole point is to *not* do that!
// one might get away with it because it is only read access to id
// but good luck debugging this...
let dogs: [Dog] = result.lazy
.flatMap { $0.objectID }
.flatMap { mainManagedObjectContext.object(with: $0) as? Dog }
// ...
我理解的方式NSAsynchronousFetchRequest
是它最好在主上下文中使用,其目的实际上是向您隐藏后台上下文业务。
So: mainContext + NSAsynchronousFetchRequest
3. 我应该如何选择?
在我看来,这NSAsynchronousFetchRequest
创建的初衷是为了简化我们的异步核心数据获取。为此,您很可能会利用它来发挥自己的优势,特别是当您需要处理进度和取消时。
但是我可能不会在我的项目中使用它,因为
- 文档很少
- 它维护得不好(永远存在错误)
- 它没有很好地适应(例如流行且优秀的 Core Data 包装器核心商店 https://github.com/JohnEstropia/CoreStore不使用它)
最后一个想法 - 在进行异步获取之前,请确保您确实需要它。首先优化查询、数据模型或批处理设置的性能可能会更好。