当表不可见时,阻止/推迟来自 NSFetchedResultsController 的 tableview 更新

Mar*_*ark 7 uitableview nsfetchedresultscontroller swift

Xcode 11.0

斯威夫特 5.1

我正在使用 Core Data 开发一个“简单”的应用程序。

单个 Core Data 实体名为 Topic,包括 Title (String)、Details (String) 和 isFavorite (Bool)

我使用的是定制的UITabBarController有3个标签- Random TopicFavorite TopicsAll Topics

最喜欢的主题和所有主题是 UITableViews 共享相同的子类,TopicsViewController.

使用自定义,TopicTabBarController我根据选项卡在 TopicsViewController 中设置了一个属性,该属性确定是否将谓词与 FetchRequest 一起用于共享此控制器的两个选项卡。

即使使用 FRC 缓存,这也能按预期工作(我对 Swift 很陌生!)

如果某个主题在任何视图上被收藏,则收藏主题和所有主题中的 tableViews 都会更新以反映该更改。这正是我想要的。

问题是我收到有关 tableView 正在更新但不可见的警告:

UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window).
Run Code Online (Sandbox Code Playgroud)

我在 at 处设置了一个象征性的断点,UITableViewAlertForLayoutOutsideViewHierarchy但目前理解这一点有点超出我的想象。

如果视图未加载,我尝试从 FRC Delegate 方法提前返回,但这显然不是解决方案。就像我说的,这对我来说都是新的。

我认为按照这篇文章的建议将 FRC Delegate 设置为 nil 并返回 self会有所帮助,但这只会阻止 managedObjectContext 保存(至少这是我在 Navicat 中看到的)。我可以逐步执行代码,并看到控制器类的正确实例正在根据我为谓词设置的自定义属性进行操作。

这是该部分的相关代码:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    self.fetchedResultsController.delegate = self
    self.performFetch()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    self.fetchedResultsController.delegate = nil
}

// MARK:- Helper methods
func performFetch() {

    do {
        try fetchedResultsController.performFetch()
    } catch {
        fatalCoreDataError(error)
    }
}
Run Code Online (Sandbox Code Playgroud)

这是保存实体的位置,上面的代码不会发生这种情况:

@objc func toggleFavorite(_ sender: UIButton) {
    let buttonPosition = sender.convert(sender.bounds.origin, to: tableView)
    if let indexPath = tableView.indexPathForRow(at: buttonPosition) {
        let topic = fetchedResultsController.object(at: indexPath)
        topic.isFavorite = !topic.isFavorite
        try! managedContext.save()
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个包含更多细节的要点。我发现以这种方式阅读要容易得多。

我也刚刚在 Apple Dev 论坛上看到了这篇文章。看起来是同样的问题,未解决。

老实说,我不知道这是太多还是太少的信息。真的希望我能在尝试解释问题时偶然发现解决方案。

谢谢你的时间。

Jim*_*des 5

对于它的价值,我收到了相同的警告,并且我能够通过执行与您尝试的非常相似的操作来修复它。基本上唯一的区别是tableView.reloadData().

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    fetchedResultsController.delegate = self
    tableView.reloadData()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    fetchedResultsController.delegate = nil
}
Run Code Online (Sandbox Code Playgroud)

...虽然我认为执行 fetch 会一样工作?