如何在Swift中合并核心数据背景上下文和主上下文之间的变化



我有一个MacOS应用程序,可以将CSV中的数据导入核心数据。由于这可能是一个长时间运行的进程,我选择在后台线程中进行导入,这样我就可以根据导入进度更新UI。因此,为了避免在将更改保存到持久存储时出现乐观锁定失败,我在后台上下文和主上下文之间合并了保存时的更改。

我认为我没有正确处理合并更改,因为当我在后台上下文中调用save时,它会调用一个阻塞UI的合并更改函数。没有一种方法可以在不阻塞UI的情况下合并上下文之间的更改吗?

以下是我如何创建我称之为moc2:的背景上下文

let app = NSApplication.shared.delegate as! AppDelegate
let container = app.persistentContainer
container.performBackgroundTask(){ (moc2) in
NotificationCenter.default.addObserver(self.app, selector: #selector(self.app.handleBackgroundCoreDataChangeInMainManagedContext(notification:)), name: NSNotification.Name.NSManagedObjectContextDidSave, object: moc2)
//perform import...
self.save(moc2: moc2)
}

以及保存功能:

func save(moc2: NSManagedObjectContext){
do {
try moc2.save()
} catch {
print(error)
}
}

这是AppDelegate中的合并更改选择器:

@objc func handleBackgroundCoreDataChangeInMainManagedContext(notification: Notification){
DispatchQueue.main.async {
self.managedObjectContext?.mergeChanges(fromContextDidSave: notification)
}
}

有没有一种方法可以在不阻塞UI的情况下使用DispatchQueue.main.async合并更改?

我在AppDelegate中测试了一个新函数,该函数从通知的对象获取上下文,然后在该上下文的线程上异步执行mergeChanges。这至少不会阻塞UI。不过,在未来的一些测试之后,我会看看这些变化是否会持续下去。

@objc func handleBackgroundCoreDataChangeInMainManagedContext(notification: Notification){
if let moc2 = notification.object as? NSManagedObjectContext {
moc2.perform {
moc2.mergeChanges(fromContextDidSave: notification)
}
}
}

最新更新