【发布时间】:2018-09-04 03:10:51
【问题描述】:
当线程不是主线程时,我在从核心数据中检索 NSManagedObj 时遇到了核心数据并发问题。
我使用了 Swift 4 的核心数据,当代码很简单时,一切都运行良好。但是,当我为核心数据添加更多代码并增加复杂度时,我偶然遇到了一个错误,并发现了核心数据的并发问题。
我遇到的错误是
CoreData: error: NULL _cd_rawData but the object is not being turned into a fault
当涉及到后台线程而不是主线程时,我搜索了一些方法来尝试通过添加以下行来处理检索核心数据操作来解决该问题。
appDelegate.persistentContainer.performBackgroundTask{....}
但是,它仍然存在问题。
首先,这里是检索函数
func retrieve() -> MasterSlave?{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
var count = 0
var masterSlave: MasterSlave?
DispatchQueue.main.async {
print("master slave receive main thread is", Thread.isMainThread)
count = appDelegate.retrieve("MasterSlave", predicate: nil, sort: nil, limit: nil)!.count
if count > 0 {
masterSlave = appDelegate.retrieve("MasterSlave", predicate: nil, sort: nil, limit: nil)?.first! as? MasterSlave
}
}
appDelegate.persistentContainer.performBackgroundTask{ context in
print("master slave receive main thread is", Thread.isMainThread)
let ms = appDelegate.retrieve("MasterSlave", predicate: nil, sort: nil, limit: nil)!
print("ms obj retreived is", ms, "count is ", ms.count)
count = appDelegate.retrieve("MasterSlave", predicate: nil, sort: nil, limit: nil)!.count
if count > 0 {
masterSlave = appDelegate.retrieve("MasterSlave", predicate: nil, sort: nil, limit: nil)?.first! as? MasterSlave
}
}
return masterSlave
}
这里是appDelegate中的retrieve函数
func retrieve(_ myEntityName:String, predicate:String?, sort:[[String:Bool]]?, limit:Int?) -> [NSManagedObject]? {
let myContext = persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: myEntityName)
// predicate
if let myPredicate = predicate {
request.predicate = NSPredicate(format: myPredicate)
}
// sort
if let mySort = sort {
var sortArr :[NSSortDescriptor] = []
for sortCond in mySort {
for (k, v) in sortCond {
sortArr.append(NSSortDescriptor(key: k, ascending: v))
}
}
request.sortDescriptors = sortArr
}
// limit
if let limitNumber = limit {
request.fetchLimit = limitNumber
}
do {
return try myContext.fetch(request) as? [NSManagedObject]
} catch {
fatalError("\(error)")
}
return nil
}
现在,发现了一些奇怪的东西:
MasterSlave 实体应该只有一个我之前保存过的对象。所以当它运行let ms = appDelegate.retrieve("MasterSlave", predicate: nil, sort: nil, limit: nil)!时,预计会检索到以下数据
data: {
encryptKey = nil;
hasMaster = 0;
lock = 0;
master = 0;
password = nil;
slave = 1;
}
但它提供了以下内容
[<MasterSlave: 0x600000280190> (entity: MasterSlave; id: 0xd000000000040004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p1> ; data: <fault>),
<MasterSlave: 0x600000280140> (entity: MasterSlave; id: 0xd000000000080004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p2> ; data: <fault>),
<MasterSlave: 0x60000009fd60> (entity: MasterSlave; id: 0xd0000000000c0004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p3> ; data: <fault>),
<MasterSlave: 0x6000002800f0> (entity: MasterSlave; id: 0xd000000000100004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p4> ; data: <fault>),
<MasterSlave: 0x6000002800a0> (entity: MasterSlave; id: 0xd000000000140004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p5> ; data: <fault>),
<MasterSlave: 0x600000280050> (entity: MasterSlave; id: 0xd000000000180004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p6> ; data: <fault>),
<MasterSlave: 0x600000280000> (entity: MasterSlave; id: 0xd0000000001c0004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p7> ; data: <fault>),
<MasterSlave: 0x60000009ff90> (entity: MasterSlave; id: 0xd000000000200004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p8> ; data: <fault>),
<MasterSlave: 0x60000009ff40> (entity: MasterSlave; id: 0xd000000000240004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p9> ; data: <fault>),
<MasterSlave: 0x60000009fef0> (entity: MasterSlave; id: 0xd000000000280004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p10> ; data: <fault>),
<MasterSlave: 0x60000009fea0> (entity: MasterSlave; id: 0xd0000000002c0004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p11> ; data: <fault>),
<MasterSlave: 0x60000009fe50> (entity: MasterSlave; id: 0xd000000000300004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p12> ; data: <fault>),
<MasterSlave: 0x60000009fe00> (entity: MasterSlave; id: 0xd000000000340004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p13> ; data: <fault>),
<MasterSlave: 0x60000009fdb0> (entity: MasterSlave; id: 0xd000000000380004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p14> ; data: <fault>),
<MasterSlave: 0x60000009fcc0> (entity: MasterSlave; id: 0xd0000000003c0004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p15> ; data: <fault>),
<MasterSlave: 0x600000280230> (entity: MasterSlave; id: 0xd000000000400004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p16> ; data: <fault>),
<MasterSlave: 0x60000009fa90> (entity: MasterSlave; id: 0xd000000000440004 <x-coredata://5FF8490C-B1C5-417D-BA3E-2F30B5D2BAD6/MasterSlave/p17> ; data: {
encryptKey = nil;
hasMaster = 0;
lock = 0;
master = 0;
password = nil;
slave = 1;
})]
当我停止应用程序并再次部署时,masterSlave 的 [NSManagedObject] 的计数变为 18 而不是 17。
我不明白为什么每次构建部署时检索到的 [NSManagedObject] 的计数都会增加。此外,当它在主线程中时,一切正常。
有人有什么想法吗?
【问题讨论】:
标签: ios swift multithreading core-data concurrency