I’m trying to get my head around background threads and manipulating CoreData via a background MOC, but I’ve ran into a bit of a snag whilst deleting a large number of records from CoreData
My setup is, I have a number of (Main) records, each of which can have 0 to several thousand (Secondary) records associated to them via a one to many relationship
This is represented by 2 view controllers in a master/detail style setup.
ViewController A has a table view that lists all of the main records. ViewController B then shows the associated records when a cell on viewController A is tapped
Both tables are populated on the main thread and the data is fetched using the persistentContainer.viewContext.
ViewController B gives the user the option to delete all of the associated records in bulk, so I would like this to be done on a background thread, so as not to block the main thread.
The problem I am having is, If I delete the records and close viewController B before the process is finished, it doesn’t delete the records. However, it deletes them fine if I leave viewController B open until the delete has finished.
One thing I have noticed, is if I do close ViewController B before the delete thread has finished, the view doesn’t deinitialize until the background delete process ends, so it seems to still be deleting after the view is closed, but it doesn’t seem to save to the persistent store unless I leave the view open until the process has finished
Here is the code i use to delete the records in the background:
class GlobalChanges....
static func deleteRecords(records: [NSManagedObject], managedContext: NSManagedObjectContext, finished: () -> Void){
//create a new background MOC
let coreDataManager = CoreDataStack.shared
let backgroundContext = coreDataManager.persistentContainer.newBackgroundContext()
backgroundContext.automaticallyMergesChangesFromParent = true
backgroundContext.performAndWait {
//remove the records from the managed context
for record in records{
let backgroundContextRecord = backgroundContext.object(with: record.objectID) as NSManagedObject
//delete the record
backgroundContext.delete(backgroundContextRecord)
}
do {
//update core data
try backgroundContext.save()
managedContext.refreshAllObjects()
finished()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
}
And this is called when user taps delete by:
@IBAction func deleteButton(_ sender: UIButton) {
let deleteQueue = DispatchQueue(label: "deleteQueue")
deleteQueue.async {
GlobalChanges.deleteRecords(records: self.selectedRows, managedContext: self.managedContext){
DispatchQueue.main.async{
//update UI...
}
}
}
}
How would I get the data to persist when closing ViewController B before the delete process has finished?
Thank in advance