'How do use CoreData in a SwiftUI app on a background Context so as not to block main thread for heavy operations

I have a swiftUI app using core data.

I have setup a CoreDataManager and I have some operations I want to perform using coreData that would block the main thread so I want to perform them on a background context.

I know that I can get a background context using:

CoreDataManager.shared.persistentContainer.newBackgroundContext()

but I believe this get's a different context each time which may cause some merging issues if done at the same time from different places.

I also can see there is a performBackgroundTask function on the shared CoreDataManager but I'm not sure which context to use in that block.

Just wondering what is the standard practice for using core data without blocking main thread. This is my stack:

class CoreDataManager {
    
    // MARK: - Properties
    
    static let shared = CoreDataManager()
    
    var persistentContainer: NSPersistentContainer!
    
    var context: NSManagedObjectContext {
        return persistentContainer.viewContext
    }
    
    // MARK: - Init Methods
    
    private init() {
        NotificationCenter.default.addObserver(self, selector: #selector(backgroundContextDidSave(notification:)), name: .NSManagedObjectContextDidSave, object: nil)
    }
    
    // MARK: - Helper Methods
    
    func prepare() {
        let groupName = Theme.appGroup
        let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupName)!.appendingPathComponent(AHTheme.databaseIdentifier)
        persistentContainer = NSPersistentContainer(name: Theme.appName)
        persistentContainer.persistentStoreDescriptions = [NSPersistentStoreDescription(url: url)]
        persistentContainer.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        context.automaticallyMergesChangesFromParent = true
    }
    
    @objc func backgroundContextDidSave(notification: Notification) {
        guard let notificationContext = notification.object as? NSManagedObjectContext else { return }
        guard notificationContext !== context else {
            return
        }
        context.perform {
            self.context.mergeChanges(fromContextDidSave: notification)
        }
    }
    
    func performBackgroundTask(block: @escaping (NSManagedObjectContext) -> Void) {
        persistentContainer.performBackgroundTask(block)
    }
    
    func saveContext() {
        do {
            if persistentContainer.viewContext.hasChanges {
                try persistentContainer.viewContext.save()
            }
        } catch {
            print(error.localizedDescription)
        }
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source