如何在后台上下文的 SwiftUI 应用程序中使用 CoreData 以免阻塞主线程进行繁重的操作
我有一个使用核心数据的 swiftUI 应用程序。
我已经设置了一个 CoreDataManager,并且我想使用 coreData 执行一些操作,这些操作会阻塞主线程,因此我想在后台上下文中执行它们。
获取后台上下文,
我知道我可以使用CoreDataManager.shared.persistentContainer.newBackgroundContext()
但我相信每次都会得到不同的上下文,如果从不同的地方同时完成,可能会导致一些合并问题。
我还可以看到共享 CoreDataManager 上有一个 PerformBackgroundTask 函数,但我不确定在该块中使用哪个上下文。
只是想知道在不阻塞主线程的情况下使用核心数据的标准做法是什么。这是我的堆栈:
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)
}
}
}
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)
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论