swift - RealmSwift RealmCollectionChange tableView 崩溃
问题描述
嗨,我正在尝试将 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
}
我的怀疑是,由于通知是在主线程的下一个 runLoop 上传递的,而且当我收到通知并且 tableView 对它做出反应时,我正在通过滚动和弄乱 UI 来使线程忙碌,它已经不同步。但我不确定这是否是问题所在,或者是否是解决方法。
谢谢
编辑
避免这种情况的一种方法只是.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)
解决方案
很好的问题,看起来 Realm 文档与您所做的完全一样(使用行而不是部分),但没有解决这个问题。我看不到一个明显的答案,但我能做的最好的就是这些可能的解决方法(尽管 tbh,两者都不是很好)。
- 重新编写更新代码以汇总结果,然后在完成后进行一次提交。
- 制作一个静态副本
sections
以在本地使用,并在订阅中更新它。即将 RealmCollection 复制到一个数组中,这不是该领域的动态视图。这将与您的更新保持同步。
我能做到的最好。否则,我看不到您如何保证动态查询和通知之间的同步。
推荐阅读
- python - 带有复数键的 defaultdict(list) python
- c++ - 由于分段错误,程序执行停止:11
- python - 如何更改矩阵的符号?
- java - 使用 Arraylist 对 Intent 的空对象引用
- python - 我可以将测试数据注入 EC2 API 调用吗
- json - 通过部分 json 更新 REST API
- python - 在 Python 中将 Wikipedia 表刮到 CSV
- android - 如何在 android 数据绑定中绑定和调用`function type`?
- firebase - 快速提问:如果您设置了使用第三方登录的用户的密码,会发生什么情况?
- java - Liferay CE 7 是否支持 Java 9?