NSFetchedResultController不在委托中调用controllerDidChangeContent

时间:2016-12-21 16:38:52

标签: ios swift core-data nsfetchedresultscontroller

在StackOverflow上有许多非常相似的问题,但我问这个问题是因为几乎所有现有问题都是由于没有在FRC上调用performFetch引起的。

在这种情况下,我们称之为。

fetchedResultsController = NSFetchedResultsController(fetchRequest: StepRecord.fetchRequest(forDate: date),
                                              managedObjectContext: theMainThreadContext,
                                                sectionNameKeyPath: nil,
                                                         cacheName: nil)

fetchedResultsController.delegate = self

do {
    try fetchedResultsController.performFetch()
} catch (let error) {
    print(error)
}

然后在后面的函数中,我们有这样的东西......

func updateScreen() {
    if fetchedResultsController.fetchedObjects.count == 0 {
        // download data and store into core data
    }

    // update the screen
}

我们有委托方法......

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    updateScreen()
}

写入核心数据的地方肯定写入backgroundThreadContext(这是我们在应用程序中多次使用的模式,它在其他地方工作)。

但是,在这种情况下,不会调用委托方法。

如果我们退出屏幕并返回updateScreen方法运行并且FRC DOES有数据。因此,获取请求是正确的,下载将记录放在正确的位置并正确保存,更新屏幕方法可以获取这些项目并填充屏幕。

我们遇到的唯一问题是没有调用委托方法。

我们在这里错过了什么吗?就像我说的那样,我们在一些地方使用了相同的模式并且它有效。只是在这种情况下,它无法正常工作。

如果您有任何其他想要查看的代码,请告诉我。如果可以,我会将其传递给您。

2 个答案:

答案 0 :(得分:0)

发生的情况是您使用不同的NSManagedObjectContext来保存下载的数据。正如您所说,该上下文使用后台队列。但也许这种背景不是FRC背景的孩子。在这种情况下,您需要合并到主上下文中,听取其他更改的通知。

但是解决它的简单方法是使用背景上下文,它是主要上下文的子项。也就是说,创建一个类型为privateQueue的新上下文,并将其parentContext设置为等于当前上下文。

答案 1 :(得分:0)

TL:DR - 不存在的对象,不会听取NSNotifications。

好的,经过一些严肃的调试后,我们终于找到了造成这个问题的问题,这很麻烦。

所以,我的问题中的代码存在于class内部,而Consumer - view controller - Factory - strongly referenced - Worker - function variable - FetchedResultsController stuff - strongly referenced 本质上是一个&#34;工作者&#34;对于工厂类。

工厂使用这个工人来创建一个对象并将其返回给工厂的所有者(&#34;消费者&#34;如果你愿意的话)。

{{1}}

虽然我们对工厂进行了强有力的参考,但工厂实际上并没有在工作所用的功能之外存储对工人的引用。

这意味着,当下载完成并将内容保存到CoreData时,Fetched Results Controller和&#34; worker&#34;实际上已不再存在于记忆中了。

因此,简单的解决方法是向工作者添加存储的引用。

更长的解决方法是重构我认为的一些代码,但那是另一天的工作。

感谢所有帮助。这无疑帮助我们解决了这个问题。