核心数据崩溃:EXC_BAD_ACCESS尝试访问使用谓词获取的数据

时间:2019-09-03 07:54:30

标签: ios swift core-data database-concurrency

我将值保存到实体方法中,该方法可以保存新数据并更新现有数据。

func saveSteps(_ serverJson: [[String: Any]]){
   let stepService = StepService(context: context);
   if(serverJson.count > 0){
     for step in serverJson {
       let stepTitle = step["stepTitle"] as? String ?? ""
       let stepDescription = step["stepDescription"] as? String ?? ""
       let stepId = step["_id"] as? String ?? ""
       let predicate: NSPredicate = NSPredicate(format: "stepId=%@", stepId)
       let stepList = stepService.get(withPredicate: predicate);
       if(stepList.count == 0){
         stepService.create(stepId: stepId, stepTitle: stepTitle, stepDescription: stepDescription);
       }else{
         if let updatableStep = stepList.first{
           updatableStep.stepDescription = stepDescription //EXC_BAD_ACCESS Error Here
           updatableStep.stepName = stepName
           updatableStep.stepTitle = stepTitle
           stepService.update(updatedStep: updatableStep)
      }else{
        stepService.create(stepId: stepId, stepTitle: stepTitle, stepDescription: stepDescription);
      }
  }


    saveContext()
}

我的Create更新和get方法位于stepService

func create(stepId:String, stepDescription: String, stepTitle:String){
   let newItem = NSEntityDescription.insertNewObject(forEntityName: "Steps", into: context) as! Steps //EXC_BAD_ACCESS Error Here
    newItem.stepId = stepId
    newItem.stepTitle = stepTitle
    newItem.stepDescription = stepDescription
}
func update(updatedStep: Steps){
  if let step = getById(id: updatedStep.objectID){
     step.stepId = updatedStep.stepId
     step.stepTitle = updatedStep.stepTitle
     step.stepDescription = updatedStep.stepDescription
}
func get(withPredicate queryPredicate: NSPredicate) -> [Steps]{
 let fetchRequest: NSFetchRequest<Steps> = Steps.fetchRequest()

    fetchRequest.returnsObjectsAsFaults = false
    fetchRequest.predicate = queryPredicate

    do {
        let response = try context.fetch(fetchRequest)
        return response

        } catch let error as NSError {
            // failure
            print(error)
            return [Steps]()
        }
    }
}

Mysave上下文方法是

// Creating private queue to save the data to disk
    lazy var savingModelcontext:NSManagedObjectContext = {
        var managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = self.coordinator

        return managedObjectContext
    }()

    // Creating Context to save in block main queue this will be temporary save
    lazy var context:NSManagedObjectContext = {
        var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.parent = self.savingModelcontext

        return managedObjectContext
    }()

func saveContext () {
    guard savingModelcontext.hasChanges || context.hasChanges else {
        return
    }

    context.performAndWait {
        do {
            try self.context.save()
        } catch let error as NSError {
            print("Could not save in Context: \(error.localizedDescription)")
        }
    }

    savingModelcontext.perform {
        do {
            try self.savingModelcontext.save()
        } catch let error as NSError {
            print("Could not save savingModelContext: \(error.localizedDescription)")
        }
    }
}

核心数据崩溃的原因有两个,一个是我访问数据以更新方法时,另一个是当我尝试使用带有实体名称的NSEntityDescription.insertNewObject创建新项时。 同时说我已经尝试用userInitiated和default的qos调度Dispach队列。我没有使用背景,因为用户可能会打开一些可能使用此背景的东西。

问题是崩溃不是conconstanct,并且在进行调试时从未崩溃,这使我不敢相信这是并发问题,但是在更新数据时永远不会删除或读取数据。

PS:我已经阅读了相同和相似问题的问题,但是在这里我无法获得有效的答案。

请及时指出我是否犯了任何错误

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

崩溃是我试图更改的原因是我在主线程中使用并使用了私有队列上下文,反之亦然。可以使用“组调度”队列来解决此问题,该队列具有用于专用队列上下文的所需QOS和用于使用主队列对象的主线程。