必须从 CoreData 调用 fetch 两次

Posted

技术标签:

【中文标题】必须从 CoreData 调用 fetch 两次【英文标题】:Having to call fetch twice from CoreData 【发布时间】:2017-01-17 00:37:04 【问题描述】:

在模拟器和我的真实设备上,应用程序终止时都会保存一组字符串。当我重新启动应用程序并为我的持久数据(从 viewDidLoad 或手动按钮操作)获取请求时,我在第一次尝试时得到一个空数组。直到我第二次 fetchRequest 我终于得到了我的数据。

有趣的是,这个问题似乎没有时间差异。在尝试第二次获取之前,我尝试设置各种超时。我是否等待 10 秒到一分钟都没关系——甚至在第一次获取后立即等待;仅在第二次尝试时获取数据。

我必须使用此代码来获取我的数据:

        var results = try self.context.fetch(fetchRequest) as! [NSManagedObject]
        while (results.isEmpty) 
            results = try self.context.fetch(fetchRequest) as! [NSManagedObject]
        
        return results

为了我的理智,这里有一个清单:

我正在使用来自 Apple 的样板代码初始化核心数据堆栈:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/InitializingtheCoreDataStack.html#//apple_ref/doc/uid/TP40001075-CH4-SW1 我将我的单个 DataController 实例放在类顶部的静态变量中 private static let context: NSManagedObjectContext = DataController().managedObjectContext 我已成功保存我的上下文,并且可以在单个会话中毫无问题地检索项目;但是在随后的会话中第一次尝试获取时,我得到了一个空数组(这就是问题所在)。

注意**我忘了提到我正在构建一个框架。我将 CoreData 与框架的包标识符一起使用并使用框架中包含的模型,因此我想避免必须使用框架之外的逻辑(除了在 appDelegate 中初始化框架)。

【问题讨论】:

【参考方案1】:

核心数据堆栈应在 appDelegate.swift 中的 applicationDidFinishLaunchingWithOptions 中初始化,因为 psc 是在您尝试获取数据后添加的。

【讨论】:

我在那张纸条上遇到的一个问题(我忘了提;很抱歉)是我在框架的上下文中使用 CoreData。除了在 didFinishLauchingWithOptions 中进行初始化之外,我不希望我的框架干扰 appDelegate 中任何其他应用程序的 CoreData 逻辑。【参考方案2】:

来自 Apple 的样板代码包括:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) 
    /* ... */
    do 
        try psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil)
     catch 
        fatalError("Error migrating store: \(error)")
    

addPersistentStoreWithType 调用完成之前,保存的数据不可用,并且这是在不同的队列上异步发生的。它会在某个时候完成,但您上面的代码在此之前正在执行。您所看到的并不令人惊讶——您基本上是在循环直到异步调用完成。

您需要以某种方式延迟获取,直到加载持久存储。有几种可能:

    做一些类似的事情,就像你已经在做的事情。我更愿意查看持久存储协调器的 persistentStores 属性,以查看是否已加载任何存储,而不是反复尝试获取。 在加载持久存储后发布通知,并在通知发生时进行提取。

【讨论】:

以上是关于必须从 CoreData 调用 fetch 两次的主要内容,如果未能解决你的问题,请参考以下文章

Javascript fetch 调用后端两次 [重复]

CoreData从后台线程读取数据仍然阻塞UI界面的原因及解决

如何防止在node.js中两次调用相同URL的获取

如何在 NSManagedObjectContext 上正确调用 fetch()?

为啥 Core Data 托管对象的 +initialize 方法会被调用两次?

RestKit / CoreData:两次请求相同的URL时插入重复的对象而不是合并