【问题标题】:CoreData performBackgroundTask conflictCoreData performBackgroundTask 冲突
【发布时间】:2018-07-22 18:10:56
【问题描述】:

我正在使用 CoreData,当我尝试在容器的 performBackgroundTask 函数中保存上下文时遇到问题。

我同时从多个地方调用它。我的理解是,每次尝试保存到persistentStore时线程都会不同,从而导致问题。

在遇到以下文章之前,我曾想过使用 childContext 和其他方法:

https://blog.five.agency/how-to-import-a-large-data-set-using-core-data-6c248a503148

文章中coreData栈如下:

final class DataCoordinator {
    //MARK: - singleton
    static let sharedInstance = DataCoordinator()

    //MARK: - init
    public var container : NSPersistentContainer
    private init() {
        container = NSPersistentContainer(name: "Model")
        container.loadPersistentStores(completionHandler: { (_, error) in
            if let error = error {
                fatalError("Unresolved error \(error)")
            }
        })
    }

    //MARK: - perform methods
    static func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) {
        DataCoordinator.sharedInstance.container.performBackgroundTask(block)
    }

    static func performViewTask(_ block: @escaping (NSManagedObjectContext) -> Void) {
        block(DataCoordinator.sharedInstance.container.viewContext)
    }
}

我的问题是使用这种方法,静态函数 performBackgroundTask 是否会克服这个问题,并且总是在同一个队列上给我相同的背景上下文,或者这与我之前每次使用 container.performBackgroundTask 所做的没有什么不同?

想知道如何在同一个队列中同时从多个位置保存数据?

【问题讨论】:

  • 与问题无关,但单例语法繁琐且过时。将private static var coordinator: DataCoordinator? 替换为static let sharedInstance = DataCoordinator() 并删除整个sharedInstance() 方法。
  • 谢谢。我已经更新了我的代码以删除单例。
  • 并编辑了代码以反映您的建议

标签: ios swift xcode core-data


【解决方案1】:

您好,第一件事与队列无关,NSManagedObjectContext 在不同的队列上运行,例如 viewContext 在主队列上运行。所以在你的情况下,我认为你想使用相同的NSManagedObjectContext 从不同的地方保存?如果是这种情况,您可以获得一个 newBackgroundContext 并保存它的引用,并使用此上下文从所有地方保存您的任务。使用NSPersistentContainer下面的方法获取背景上下文。

func newBackgroundContext() -> NSManagedObjectContext

如果我对您的问题的理解有误,请告诉我更多信息,以便我为您提供其他解决方案。

同样,你提到的教程的以下方法对你不起作用

static func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void) {
        DataCoordinator.sharedInstance().container.performBackgroundTask(block)
    }

因为performBackgroundTask 总是创建一个新的上下文。苹果文档说:

每次调用此方法时,持久化容器都会创建一个新的 NSManagedObjectContext,并将 concurrencyType 设置为 NSManagedObjectContextConcurrencyType.privateQueueConcurrencyType.。然后持久化容器会针对上下文私有队列上新创建的上下文执行传入的块。

【讨论】:

  • 我明白你的意思,但我想知道是否将其设为静态函数只会调用 performBackgroundTask 函数一次并以与将静态放在变量前面相同的方式传递它。如果是这样,它应该只适用于一种上下文。
  • 你是说它是一个静态函数,所以总是在相同的上下文中工作?
  • 我在问是不是这样。我之前没用过静态函数
  • 好的,尽管它是静态函数。每次你打电话时,它都会在新的上下文中执行任务。
猜你喜欢
  • 1970-01-01
  • 2017-01-29
  • 1970-01-01
  • 2017-08-23
  • 2013-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
相关资源
最近更新 更多