ios - 观察 Realm 结果集的变化
问题描述
我正在开发一个使用 Realm 数据库的 iOS 应用程序。在我的AppDelegate
中,我定义了一个 Realm 结果集,如下所示:
var results: Results<RealmWidget>!
var notificationToken: NotificationToken? = nil
do {
let realm = try Realm()
if results == nil {
results = realm.objects(RealmWidget.self)
}
} catch {
print(error.localizedDescription)
}
我观察到这个结果集的变化如下:
if notificationToken == nil {
notificationToken = results.observe { (changes: RealmCollectionChange) in
switch changes {
case .update(_, _, let insertions, _):
if insertions.count > 0 {
// show badge on tab bar
// play sound to get the user's attention
}
default:
break
}
}
}
每当在数据库中插入新RealmWidget
对象时(由于从服务器接收数据而发生),我想UITabBar
在我的 UI 中显示一个徽章。此代码似乎工作正常。
在我的应用程序的另一部分,我有一个视图控制器,UITableView
它用于显示所有RealmWidget
对象(按时间戳排序)。在该视图控制器内部,我还有一个结果集,我观察它的变化,因此我知道何时重新加载 tableview。该代码如下所示:
var results: Results<RealmWidget>!
var notificationToken: NotificationToken? = nil
class MyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
results = RealmHelper.getRealmWidgets() // helper method that queries Realm for all of the Widget objects and sorts them by timestamp
notificationToken = results.observe { [weak self] (changes: RealmCollectionChange) in
DispatchQueue.main.async {
self!.tableView.reloadData()
}
}
}
}
这段代码似乎也能正常工作,直到我在AppDelegate
. 然后我意识到,每当我从这个视图控制器中删除一行时UITableView
,我也会听到声音播放。这是出乎意料的,因为我应该只在UITabBar
插入而不是删除时将徽章添加到并播放声音。
我在我定义的观察块中添加了一些调试代码,AppDelegate
所以它看起来像这样:
if notificationToken == nil {
notificationToken = results.observe { (changes: RealmCollectionChange) in
switch changes {
case .update(_, let deletions, let insertions, let modifications):
print("widget deletion count: \(deletions.count)")
print("widget insertion count: \(insertions.count)")
print("widget modification count: \(modifications.count)")
if insertions.count > 0 {
// show badge on tab bar
// play sound to get the user's attention
}
default:
break
}
}
}
当我运行应用程序时,使用 tableview 切换到视图控制器,然后删除其中一行(这会导致RealmWidget
从数据库中删除相应的对象),我在调试控制台中看到以下输出:
widget deletion count: 2
widget insertion count: 1
widget modification count: 0
我不清楚这方面的一些事情:
- 为什么我只删除了一个 RealmWidget 对象时删除计数为 2?
- 当我没有添加/插入任何 RealmWidget 对象时,为什么插入计数为 1?
如果有人可以解释这里发生的事情,我当然会感谢您的帮助!
- 编辑 -
我在视图控制器内部定义的观察块中添加了相同的调试代码,并注意到其他一些奇怪的东西。当这个“问题”发生时,我在调试控制台中看到这个输出:
widget deletion count (AppDelegate): 2
widget insertion count (AppDelegate): 1
widget modification count (AppDelegate): 0
widget deletion count (View controller): 1
widget insertion count (View controller): 0
widget modification count (View controller): 0
因此,我的视图控制器中的观察块显示 1 个删除,但我的 AppDelegate 中的观察块显示 2 个删除和 1 个插入!奇怪的是,这并不是 100% 发生的。如果我UITableView
正在显示 10 个RealmWidget
对象并且我一次删除一个对象,大约 75% 的时间,我会在控制台中看到上述输出。但另外 25% 的时间,输出正是我所期望看到的:
widget deletion count (AppDelegate): 1
widget insertion count (AppDelegate): 0
widget modification count (AppDelegate): 0
widget deletion count (View controller): 1
widget insertion count (View controller): 0
widget modification count (View controller): 0
两个观察块中的 1 个删除。我现在比以前更糊涂了!;-)
-- 编辑 #2 --
似乎这种行为与Results<RealmWidget>
我的 AppDelegate 和Results<RealmWidget>
我的视图控制器中的 没有以相同的方式对查询结果进行排序这一事实有关。
在我的AppDelegate
,是领域中所有对象results
的未排序集合。RealmWidget
但是在我的视图控制器中,我用来定义的辅助方法是Realm 中所有对象results
的排序集合。RealmWidgets
解决方案
我通过 GitHub 将这个问题发布到 Realm 并得到以下回复:
是的,当对象被删除时,未排序的结果会重新排列。如果您不要求明确的排序顺序,那么对象只是按照它们碰巧存储在磁盘上的顺序列出,这是一个不稳定的顺序,当对象被删除时会发生变化。
我们目前报告最后的对象移动到已删除对象的位置,因为该对象也被删除然后插入新位置。
推荐阅读
- rabbitmq - Celery 4.3.0 - 向任务发送信号而不终止
- c# - 如何为将字符串数组作为参数的 .Net Core 3.1 webapi 服务调用定义路由?
- sql-server - 如何运行会使其他查询运行更慢的 SQL Server 查询
- c++ - C++ 编译时特征值评估
- azure - 具有多个协变量特征的时间序列的 Azure AutoML 预测示例
- java - 自定义对话框 - 指定的孩子已经有一个父母
- javascript - 如何以角度获取具有相同名称但在不同界面中的数据
- postgresql - 取消或终止查询的日志是什么?
- python - 如何使用不均匀的子数组作为瓷砖来平铺一维 numpy 数组?
- sql - 删除重复记录,仅当记录差异小于 2 分钟时才保留最早