我正在使用Apple的并发核心数据调试器。
-com.apple.CoreData.ConcurrencyDebug 1
我不时得到public static func find(arrayBy predicate: NSPredicate, sort: [NSSortDescriptor] = [], limit: Int? = nil) -> [Self] {
let fetchRequest = NSFetchRequest<Self>(entityName: "\(Self.self)")
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = sort
do {
return try Context.current.fetch(fetchRequest) // Exception!!!
} catch let error {
Logger.fatal("Failed to perform fetch: \(error)")
return []
}
}
,即使我几乎可以确定线程没有被违反。
这是发生异常的代码的一部分(代码是扩展NSManagedObject的协议的一部分):
perform:
代码在上下文的(lldb) po Context.current
<StoreContext: 0x7f854b556610>
块中执行。
这是线程信息:
conversion functions in netinet/in.h
和debuger信息确认在右侧NSManagedContext上执行了执行:
po fetchRequest.entityName!
"Position"
成功提取实体名称:
(lldb) po fetchRequest.predicate!
ANY employees.company.id == "282372"
Predicate由纯String对象构成(根本不使用托管对象):
po fetchRequest.sortDescriptors!
0 elements
在这种情况下根本不使用排序描述符:
Context.current
完全忽略了限制。
我错过了什么?有没有人知道这里有什么问题?
修改
为了澄清,Context.current = managedObjectContext
managedObjectContext.performAndWait {
//...
}
是在调度块之前设置的:
Thread 13
您可以在屏幕截图中看到Queue: NSManagedObject 0x7f854b556610 (serial)
正在Context.current
上运行。此外,发生异常时<StoreContext: 0x7f854b556610>
会返回this
。通过查看内存地址,很容易得出结论块正在正确的队列中执行。
答案 0 :(得分:4)
将“当前”背景上下文存储在全局状态是一种不好的做法。我无法指出代码中的确切位置,但是当涉及多线程时,全局状态会发生意外情况。将find
功能更改为接受context
作为参数。这将避免使用任何全局状态,并可能解决您的问题。
答案 1 :(得分:3)
推荐以避免使用.performAndWait
API,仅在极少数情况下最稀有的情况下使用,当其他所有内容都failed!时
在整个应用程序中评估变形Context.current
到managedObjectContext.perform
此更改的效果是在所有数据库操作中添加异步性
听到大量更改可能会让我感到信任但是相信我,只是决定将Core Data视为一个完全异步的API&amp;这样的生活会好得多。
我确定您当前遇到的崩溃是.performAndWait
答案 2 :(得分:3)
查看此博客,以便更好地了解Core Data中的多线程