一直以来,数据持久化使用的是sqlite,后半年的新项目选择使用Apple的CoreData,果然如传说的那样再也没有那些烦躁的sql语句了,测试阶段也没有发现很大的问题,结果上线crash 8成全是CoreData引起的。
经过几个版本迭代修复 ,还是存在Crash,也是醉了,真的鸡肋啊?。。。?/p>
就Crash的情况做个简单的总结
1 CoreData 线程不安全的。
CoreData:__65-[NSPersistentStoreCoordinatorexecuteRequest:withContext:error:]_block_invoke.547+8120
在多线程操作CoreData时就有了Crash风险,建议拒绝在多线程频繁操作CoreData,修复后Crash明显减少了。
2 CoreData 操作一个实体时候,建议创建一个上下文,而不是多个上下文。多个上下文CoreData会发出警告,这种警告千万不能忽略,要及时处理。这就是为啥CoreData设置成一个单利的原因。修复后明显减少了。
warning: 'StampsInfo' (0x303f28fd0) from NSManagedObjectModel (0x302b6bb10) claims 'StampsInfo'.
还有一些警告 可以参考 https://forums.kodeco.com/t/multiple-warnings-when-running-unit-tests-in-sample-app/74860/8 的解决方案
2 CoreData:_PFCMT_SetValue+744
原因未知。推测是查询太频繁引起的,使用场景是funccaptureOutput(_output:AVCaptureOutput,didOutputsampleBuffer:
CMSampleBuffer,fromconnection:AVCaptureConnection)使用的,这个方法相机实时输出里面用的。修复后,新版本没出现。
3 CoreData: __65-[NSPersistentStoreCoordinator executeRequest:withContext:error:]_block_invoke.541 + 8060
有问题的代码
// MARK: get all cameras
/// 查询相机列表数据
func queryCamerasInfo() -> [CameraInfo] {
let req = CameraInfo.fetchRequest()
// req.predicate = NSPredicate(format: "userId = %@",id)
let context = persistentContainer.viewContext
do {
let fetchedObjects = try context.fetch(req)
guard fetchedObjects.count > 0 else{return []}
return fetchedObjects
}
catch {}
return []
}
原因未知,改成如下:
func queryCamerasInfo() -> [CameraInfo] {
let req = CameraInfo.fetchRequest()
// req.predicate = NSPredicate(format: "userId = %@",id)
let context = persistentContainer.viewContext
// do {
// 这里查询有闪退
let fetchedObjects = try? context.fetch(req)
if let fetchedObjects = fetchedObjects {
guard fetchedObjects.count > 0 else{return []}
return fetchedObjects
}
// }
// catch {}
return []
}
把try改成try?
,后续观察一下。
4 CoreData: _PFObjectIDFastHash64 + 64
https://developer.apple.com/forums/thread/662240?page=2
https://forums.developer.apple.com/forums/thread/662240
原因很迷茫?。。?!