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

时间:2017-02-02 10:39:10

标签: ios swift multithreading core-data swift3

我正在使用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。通过查看内存地址,很容易得出结论块正在正确的队列中执行。

3 个答案:

答案 0 :(得分:4)

将“当前”背景上下文存储在全局状态是一种不好的做法。我无法指出代码中的确切位置,但是当涉及多线程时,全局状态会发生意外情况。将find功能更改为接受context作为参数。这将避免使用任何全局状态,并可能解决您的问题。

答案 1 :(得分:3)

推荐以避免使用.performAndWait API,仅在极少数情况下最稀有的情况下使用,当其他所有内容都failed!时 在整个应用程序中评估变形Context.currentmanagedObjectContext.perform 此更改的效果是在所有数据库操作中添加异步性 听到大量更改可能会让我感到信任但是相信我,只是决定将Core Data视为一个完全异步的API&amp;这样的生活会好得多。
我确定您当前遇到的崩溃是.performAndWait

损坏行为的复合结果

Thisthisthis对该主题有一些很好的解读。

答案 2 :(得分:3)