'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 |
|---|
