必须从 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 两次的主要内容,如果未能解决你的问题,请参考以下文章
CoreData从后台线程读取数据仍然阻塞UI界面的原因及解决
如何在 NSManagedObjectContext 上正确调用 fetch()?