首页 > 解决方案 > CoreData 在从同一线程读取获取的对象属性时崩溃

问题描述

下面,我有 3 个与 CoreData 以不同方式在不同线程中获取对象相关的代码片段。其中一种方法是当我在从 DB 中获取数据后尝试读取数据时使用 EXC_BAD_INSTRUCTION 崩溃,即使获取和读取是在同一个线程上完成的。

print("hello: current thread is \(Thread.current)")
let moc = self.getChildMoc()
moc.performAndWait {
    let contacts = PPContactSyncHelper.contactsIfExistsWith(connectIds: connectIds, moc: moc)
    contacts.forEach { contact in
        print("hello: 2. current thread is \(Thread.current)")
        print("hello: \(contact.connectId)")
    }
}
        
DispatchQueue.main.async {
    let abContacts = PPContactSyncHelper.contactsIfExistsWith(connectIds: connectIds, moc: self.mainContext)
    abContacts.forEach { abContact in
        print("hello: \(abContact.connectId)")
    }
}
        
let contacts = PPContactSyncHelper.contactsIfExistsWith(connectIds: connectIds,
                                                                moc: moc)
contacts.forEach { contact in
    print("hello: 2. current thread is \(Thread.current)")
    print("hello: \(contact.connectId)")
}

最后一个片段是导致问题的片段,而其他片段可以成功读取数据。

这就是我正在做的事情。

  1. 我创建了一个新的子上下文,类型为 privateQueueConcurrencyType,父设置为 mainContext
  2. 我首先使用 performAndWait 使用此上下文来获取和读取正常工作的数据。
  3. 然后我尝试使用 mainContext 在主线程中获取和读取。这也有效。
  4. 当我尝试在同一个线程上使用子上下文获取并在没有执行块的情况下读取时,即使我在同一个线程上,它也会崩溃。

该函数PPContactSyncHelper.contactsIfExistsWith使用提供的上下文从 performAndWait 块内的 coredata 获取数据。

我在这里想念什么?

标签: iosswiftmultithreadingcore-dataconcurrency

解决方案


对于托管对象上下文,您始终需要使用performor performAndWait。除了一种情况:如果您使用主队列托管对象上下文并且在主队列上运行,则可以跳过这些方法。

在您的示例中:

  • 示例 1 有效,因为您使用了performAndWait. 这是一个私有队列(不是主队列)上下文,并且您正确使用了它。
  • 示例 2 有效,因为它是一个主队列上下文,并且您使用了DispatchQueue.main.async. 这是我上面提到的一个例外,所以你可以在哪里。
  • 示例 3 不起作用,因为您使用的是私有队列上下文,但您没有使用performor performAndWait。您需要在此处使用其中之一以避免崩溃。您与示例 1 在同一线程上,但这没关系。重要的是您的 Core Data 代码是否在上下文的队列中运行。

推荐阅读