核心数据崩溃:EXC_BAD_ACCESS 尝试访问使用谓词获取的数据时
Core data Crash: EXC_BAD_ACCESS while trying access data got using predicate
我已将值保存到实体方法,该方法保存新数据并更新现有数据。
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()
}
我的创建更新和获取方法在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 和默认的 qos 的 Dispach 队列。我没有使用后台,因为用户可能会打开一些可能使用它的东西。
问题是崩溃不一致,调试时从未崩溃,这让我相信这是并发问题,但数据在更新时从未被删除或读取。
PS:我已经阅读了具有相同和相似问题的问题,但我无法在这里得到有效的答案。
如有错误请小朋友指出
非常感谢任何帮助
崩溃的原因是我试图改变的是我在主线程中使用和使用私有队列上下文,反之亦然。使用具有所需 QOS 的 Group Dispach 队列解决此问题,用于私有队列上下文和主线程,用于使用主队列对象。
我已将值保存到实体方法,该方法保存新数据并更新现有数据。
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()
}
我的创建更新和获取方法在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 和默认的 qos 的 Dispach 队列。我没有使用后台,因为用户可能会打开一些可能使用它的东西。
问题是崩溃不一致,调试时从未崩溃,这让我相信这是并发问题,但数据在更新时从未被删除或读取。
PS:我已经阅读了具有相同和相似问题的问题,但我无法在这里得到有效的答案。
如有错误请小朋友指出
非常感谢任何帮助
崩溃的原因是我试图改变的是我在主线程中使用和使用私有队列上下文,反之亦然。使用具有所需 QOS 的 Group Dispach 队列解决此问题,用于私有队列上下文和主线程,用于使用主队列对象。