Запретить / отложить обновления табличного представления из NSFetchedResultsController, когда таблица не видна - PullRequest
2 голосов
/ 27 сентября 2019

Xcode 11.0

Swift 5.1

Я работаю над "простым" приложением, использующим Core Data.

Один объект Core Data называется Тема и содержит Заголовок(String), Details (String) и isFavorite (Bool)

Я использую пользовательский UITabBarController с 3 вкладками - Random Topic, Favorite Topics и All Topics

Избранные темыи все темы являются UITableView, совместно использующими один и тот же подкласс, 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).

Я установил символическую точку останова на UITableViewAlertForLayoutOutsideViewHierarchyно осмысление этого сейчас немного выше моей.

Я пытался вернуться из методов делегата FRC раньше, если представление не было загружено, но это явно не было решением.Как я уже сказал, это все для меня в новинку.

Я думал, что установка делегата FRC на nil и обратно на себя, как , предложенное в этом посте, , поможет, но это только предотвращает от управляемогоObjectContextсохранение (по крайней мере, это то, что я вижу с 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)
    }
}

Здесь сохраняется объект, чего не происходит с указанным выше кодом:

@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()
    }
}

Вот Gist с более подробной информацией .Мне гораздо проще читать таким образом.

Я также только что натолкнулся на этот пост на форуме Apple Dev.Похоже, та же проблема, неразрешенная.

Честно говоря, я не знаю, слишком много или мало информации.Очень надеялся, что я наткнулся на решение, пытаясь объяснить проблему.

Спасибо за ваше время.

1 Ответ

0 голосов
/ 30 сентября 2019

Что бы это ни стоило, я получил то же самое предупреждение, и я смог это исправить, выполнив что-то очень похожее на то, что вы пробовали.По сути, единственным отличием является 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
}

... хотя я думаю, что выполнение выборки будет работать точно так же?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...