首页 > 解决方案 > 违反 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!;
    }

标签: iosswiftcore-data

解决方案


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
}

上面是这种违规的一个例子,因为资源是在某个队列上获取的,然后传递给全局的。


推荐阅读