RealmSwift RealmCollectionChange tableView сбой - PullRequest
0 голосов
/ 21 февраля 2019

Hy, я пытаюсь связать RealmNotifications с обновлением tableView, но по какой-то причине это продолжает генерировать несколько сбоев в tableView из-за несоответствия между количеством существующих разделов и тем, что отправлено уведомление области.Это код, который я имею для наблюдения за любыми изменениями на Results<T>:

do {
            let realm = try Realm()
            sections = realm.objects(AssetSections.self).filter("isEnabled = true AND (assets.@count > 0 OR isLoading = true OR banners.@count > 0 OR tag == 'My Tools')").sorted(byKeyPath: "sort_order", ascending: true)

            guard let sections = sections else { return }

            // Watch on the asset sections
            notificationToken = sections.observe { [weak self] (change: RealmCollectionChange) in
                switch change {
                case .initial: break
                case .error(let error):
                    self?.handle(error: error)

                case .update(_, let deletions, let insertions, let modifications):
                    self?.updatedModel.onNext((insertions: insertions, modifications: modifications, deletions: deletions))
                }
            }
        } catch { }

Приведенный выше код происходит в ViewModel, и ViewController наблюдает эти изменения следующим образом:

vm.updatedModel
            .subscribe(onNext: { [weak self] (insertions, modifications, deletions) in
                guard let `self` = self else { return }

                self.tableView.beginUpdates()
                self.tableView.insertSections(insertions, animationStyle: .none)
                self.tableView.deleteSections(deletions, animationStyle: .none)
                self.tableView.reloadSections(modifications, animationStyle: .none)
                self.tableView.endUpdates()
            })
            .disposed(by: disposeBag)

Я работаю с разделами, а не со строками, потому что это tableView с несколькими разделами и только одной строкой на раздел.

Сбой, который я получаю, - это если я пытаюсь обновить, который выполняет несколько сетевых вызововкоторый в свою очередь вносит множественные изменения в объекты.Самое смешное, что я всегда могу почти повторить сбой, если быстро прокрутить вниз во время вытягивания, чтобы обновить.Ошибка заключается в следующем:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete section 14, but there are only 14 sections before the update'

Способ получения numberOfSections для tableView следующий:

var numberOfSections: Int {
        return sections?.count ?? 0
    }

Я подозреваю, что, поскольку уведомления доставляются наследующий цикл выполнения основного потока, и поскольку я делаю поток занятым, прокручивая и связываясь с пользовательским интерфейсом к тому времени, когда я получаю уведомление, и tableView реагирует на него, он уже не синхронизирован.Но я не совсем уверен, если это проблема или как ее решить.

Спасибо

Редактировать

Один из способов избежать этого - просто .reloadData() на tableView, но это удар по производительности, особенно для больших наборов данных, и я не могу использовать стандартные анимации tableView.Чтобы уменьшить эффект от вызова .reloadData() несколько раз, я использую debounce .

vm.updatedModel
            .debounce(1.0, scheduler: MainScheduler.instance)
            .subscribe(onNext: { [weak self] (insertions, modifications, deletions) in
                guard let `self` = self else { return }

                self.tableView.reloadData()
            })
            .disposed(by: disposeBag)

1 Ответ

0 голосов
/ 22 февраля 2019

Отличный вопрос, и похоже, что документация Realm работает точно так же, как вы (со строками, а не с разделами), но не решает эту проблему.Я не вижу очевидного ответа, но лучшее, что я могу сделать, - это возможные обходные пути (хотя tbh, ни то, ни другое).

  1. Переработать код обновления, чтобы собрать воедино результаты, а затем выполнить один коммит.когда они будут завершены.
  2. Сделайте статическую копию sections для локального использования и обновите ее в рамках подписки.т.е. скопировать коллекцию RealmCollection в массив, который не является динамическим представлением области.Это будет синхронизироваться с вашими обновлениями.

Лучшее, что я могу сделать.В противном случае я не вижу, как можно гарантировать синхронизацию между динамическим запросом и уведомлением.

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