skip to Main Content

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


  1. 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.

    Login or Signup to reply.
  2. In general we should work with the context only on its own thread (main – for viewContext, private background – for background context).

    The way to ensure it is to use perform and performAndWait 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 as backgroundContext saves since mainContext.automaticallyMergesChangesFromParent = true.

    You may also consider the idea proposed by @adonoho. Sample.
    All you have to do is:

    mainContext.parent = backgroundContext
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search