So my questions is, Is it right way if we use backgroundContext in main thread ?
Here I want to use ‘performAndWait’ so the statements after this CoreData operation should execute after CoreData save.
private lazy var backgroundContext: NSManagedObjectContext = {
let bgContext = self.persistentContainer.newBackgroundContext()
bgContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
bgContext.automaticallyMergesChangesFromParent = true
return bgContext
}()
private lazy var viewContext: NSManagedObjectContext = {
let mainContext = self.persistentContainer.viewContext
mainContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
mainContext.automaticallyMergesChangesFromParent = true
return mainContext
}()
backgroundContext.performAndWait {
// create or edit entity
..........
// save
do {
// Verify the background context has changes, We are using background context as Lazy.
if backgroundContext.hasChanges {
// Save context
try backgroundContext.save()
}
// Verify the main context has changes
guard viewContext.hasChanges else { return }
// Wait before complete existing operation
viewContext.performAndWait {
do {
// Save context
try viewContext.save()
print("save changes")
} catch {
print("error - (error.localizedDescription)")
}
}
} catch {
fatalError("Failure to save context: (error)")
}
// here perform UI operations only after saving data.
2
Answers
A known good strategy is to make your main thread context be a child context of a background context. Then saves are fast and done on the background. Reads are frequently serviced from the main thread. If you have some large insertions to perform, the perform them on a background child context of the main context. As the save is percolated up the context chain, the UI remains responsive.
In general we should work with the context only on its own thread (main – for
viewContext
, private background – forbackground context
).The way to ensure it is to use
perform
andperformAndWait
which you do. So this part is fine. People run into issues when they mix threads.It is unclear why do you save twice.
viewContext
should automatically merge changes from coordinator asbackgroundContext
saves sincemainContext.automaticallyMergesChangesFromParent = true
.You may also consider the idea proposed by @adonoho. Sample.
All you have to do is: