I have save values to entity method which save new data and updates existing data.
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()
}
My Create update and get methods are in 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 context method is
// 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)")
}
}
}
There are two places that core data crashes with same error message one is when i access the data to update the method and other is when i am trying to create a new item using NSEntityDescription.insertNewObject with entity name. while saing i have tried Dispach queue with qos of userInitiated and default. I didn't use background as user might open some thing that might use this.
The problem is the crash is not consistanct and has never crashed when doing a debug which leads me to belive it is concurrency issue but the data is never deleted or read when being updated.
PS: I have read the questions with same and similar issues but i could not get a working answer here the question.
Kidly point out if i have made any mistakes
Thanks any help is appreciated
The Reason fo the crash was i was trying to change was that i was using and using private queue context in main thread and vise versa. to fix this using Group Dispach queue with desired QOS for private queue context and main thread for using main queue objects.