ios - 违反 Core Data 的线程合约EXC_BREAKPOINT (code=1, subcode=0x1f0ad1c8c)
问题描述
上传任务时我面临一个异常。我在后台启动进程并获取核心数据记录,我不知道我怎么能违反核心数据的并发模型。请检查以下代码。
//Call methods in background
DispatchQueue.global(qos: .background).async {
let onsourceNetwork = OnsourceNetworkUtility(withServiceRequestId: resources.value(forKey: "ServiceRequestId") as! String, inspectorId: resources.value(forKey: "InspectorId") as! String)
onsourceNetwork?.delegate = self
onsourceNetwork?.uploadResources()
}
此方法出现异常。
//Fetch data from the core data
func fetchResourcesToBeUploaded(serviceRequestId: String, inspectorId: String) -> [ResourceMO] {
let currentMOC = self.getCurrentContext()
//upload status whether all chunks has been uploaded for a resource or not
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Resource")
request.predicate = NSPredicate(format: "(serviceRequestId = %@ AND inspectorId = %@ AND uploadStatus = %@ OR uploadStatus = %@)", serviceRequestId, inspectorId, UploadStatus.Started.rawValue, UploadStatus.InProgress.rawValue)
request.returnsObjectsAsFaults = false
var resources = [ResourceMO]()
do {
resources = try currentMOC.fetch(request) as! [ResourceMO]// Core Data Violate here
} catch {
//print("Failed")
}
return resources;
}
这是获取上下文代码:
func getCurrentContext() -> NSManagedObjectContext {
var curMOC:NSManagedObjectContext? = self.managedObjectContext
let thisThread:Thread = Thread.current
if thisThread == Thread.main {
if curMOC != nil {
return curMOC!
}
let coordinator:NSPersistentStoreCoordinator? = self.persistentStoreCoordinator
if coordinator != nil {
curMOC = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
curMOC?.persistentStoreCoordinator = coordinator
}
return curMOC!
}
// if this is some other thread....
// Get the current context from the same thread..
var threadManagedObjectContext:NSManagedObjectContext? = thisThread.threadDictionary.object(forKey:"ManagedObjectContext_Key") as? NSManagedObjectContext;
// Return separate MOC for each new thread
if threadManagedObjectContext != nil {
return threadManagedObjectContext!;
}
let coordinator:NSPersistentStoreCoordinator? = self.persistentStoreCoordinator
if coordinator != nil {
threadManagedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType)
threadManagedObjectContext?.persistentStoreCoordinator = coordinator
threadManagedObjectContext?.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
threadManagedObjectContext?.undoManager = nil
threadManagedObjectContext?.parent = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.mainQueueConcurrencyType)
thisThread.threadDictionary.setObject(threadManagedObjectContext!, forKey: "ManagedObjectContext_Key" as NSCopying)
assert((threadManagedObjectContext != nil))
}
return threadManagedObjectContext!;
}
解决方案
您fetchResourcesToBeUploaded
从不同的线程调用,而不是DispatachQueue.global
. 确保您在同一线程上获取和使用资源,例如通过将整个上传逻辑包装在DispatchQueue.global
块中:
DispatchQueue.global(qos: .background).async {
let resources = // call fetchResourcesToBeUploaded
// other code
let onsourceNetwork = OnsourceNetworkUtility(withServiceRequestId: resources.value(forKey: "ServiceRequestId") as! String, inspectorId: resources.value(forKey: "InspectorId") as! String)
onsourceNetwork?.delegate = self
onsourceNetwork?.uploadResources()
}
您需要确保始终在同一个线程上获取和使用对象。在一个线程上获取对象然后将它们传递给另一个线程是违反多线程的:
let resources = // call fetchResourcesToBeUploaded
DispatchQueue.global(qos: .background).async {
// use resources
}
上面是这种违规的一个例子,因为资源是在某个队列上获取的,然后传递给全局的。
推荐阅读
- python - 从字典值中提取数组
- api - 如何使用 Sabre_OTA_ProfileUpdateRQ 修改特定元素
- python - Discord,py 全球禁令命令
- python - kivy FileChooserListView on_selection 事件未按预期工作
- c# - 进程退出后删除时文件被使用异常
- java - 我可以在 Spring Boot 的注释类级别中使用占位符吗?
- javascript - 将数据保存在特定的行和列中
- powershell - 在 powershell 中添加命令 add-teamChannelUser 会发生什么?
- c - 为什么转换(无符号长长)DBL_MAX(或 FLT_MAX)也会导致 FE_INEXACT 升高?
- javascript - 在 React 中更改页面时 Apexchart 消失