意外的核心数据多线程违规

XeN*_*NoN 12 multithreading core-data ios swift swift3

我正在使用Apple的并发核心数据调试器.

-com.apple.CoreData.ConcurrencyDebug 1

我不时得到__Multithreading_Violation_AllThatIsLeftToUsIsHonor__,即使我几乎可以肯定线程没有被违反.

这是发生异常的代码的一部分(代码是扩展NSManagedObject的协议的一部分):

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 []
    }
}
Run Code Online (Sandbox Code Playgroud)

代码在上下文perform:块中执行.

这是线程信息:

在此输入图像描述

和debuger信息确认在右侧NSManagedContext上执行了执行:

(lldb) po Context.current
<StoreContext: 0x7f854b556610>
Run Code Online (Sandbox Code Playgroud)

实体名称已成功提取:

po fetchRequest.entityName!
"Position"
Run Code Online (Sandbox Code Playgroud)

谓词由纯String对象构成(根本不使用托管对象):

(lldb) po fetchRequest.predicate!
ANY employees.company.id == "282372"
Run Code Online (Sandbox Code Playgroud)

在这种情况下,根本不使用排序描述符:

po fetchRequest.sortDescriptors!
0 elements
Run Code Online (Sandbox Code Playgroud)

限制完全被忽略.

我错过了什么?有谁知道这里有什么不对吗?

编辑:

为了澄清,Context.current在调度块之前设置:

Context.current = managedObjectContext
managedObjectContext.performAndWait {
   //...
}
Run Code Online (Sandbox Code Playgroud)

您可以在Thread 13正在运行的屏幕截图上看到Queue: NSManagedObject 0x7f854b556610 (serial).此外,当发生异常时Context.current返回<StoreContext: 0x7f854b556610>.通过查看内存地址,很容易得出结论,块正在正确的队列中执行.

yst*_*ack 3

建议避免使用.performAndWaitAPI,仅在极少数情况下使用,当其他一切都失败时!
评估整个应用程序的Context.current变形。此更改的效果将是在所有数据库操作 中增加异步性。 这听起来可能是一个巨大的改变,但相信我,只要决定将 Core Data 视为完全异步的 API,这样生活就会好得多。 我确信您当前面临的崩溃是由于以下原因导致的:managedObjectContext.perform


.performAndWait

Thisthisthis是有关该主题的一些不错的读物。