Recently I took over the development of an existing iOS project based on Core Data. The project uses a background sync for retrieving and updating data from the server and to write it to Core Data. However, in some cases this leads to a crash in the following block:
context.perform {
print("Replacing \(type) \(serverId)")
var modifiedObject = modifiedObject
modifiedObject.serverId = serverId
modifiedObject.modified = false
do {
try context.save()
}
catch {
print(error)
print("could not save context")
}
fulfill(())
}
The context of the above block is earlier created in a background context:
let context = self.persistentContainer.newBackgroundContext()
context.mergePolicy = NSMergePolicy(merge:
NSMergePolicyType.mergeByPropertyStoreTrumpMergePolicyType)
context.stalenessInterval = 0
The app doesn't throw an error in the catch block, but stops working when accessing the context. No further log details can be found.
In most of the Core Data examples I've seen, persistentContainer.viewContext
is used, or newBackgroundContext()
for background operations. In this app, on the main thread the app by default uses the context registered to the object itself. See the following example:
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: location.managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil)
The value of the property managedObjectContext
is the context that is registered to the object. Therefore my assumption is the value changes and thereby an incorrect context is used. I think this causes a thread access issue.
Has anyone else experienced these issues when the registered context is used directly and how did you work around it?