我正在开发一个使用 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
上显示一个角标(Badge)在我的用户界面中。此代码似乎工作正常。
在我的应用程序的另一部分,我有一个带有 UITableView
的 View Controller 用于显示所有 RealmWidget
对象(按时间戳排序)。在那个 View Controller 内部,我还有一个结果集,我观察它的变化,所以我知道什么时候重新加载 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
中的观察 block 中播放声音之前,这段代码似乎也能正常工作。 .然后我意识到,我随时删除 UITableView
中的一行在这个 View Controller 中,我也听到了声音播放。这是出乎意料的,因为我应该只将角标(Badge)添加到 UITabBar
并在插入而不是删除时播放声音。
我在 AppDelegate
中定义的观察 block 中添加了一些调试代码所以它看起来像这样:
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 的 View Controller ,然后删除其中一行(这会导致相应的 RealmWidget
对象从数据库中删除),我在调试中看到以下输出控制台:
widget deletion count: 2
widget insertion count: 1
widget modification count: 0
关于这方面的一些事情我不清楚:
- 为什么我只删除了一个 RealmWidget 对象时删除计数为 2?
- 为什么我没有添加/插入任何 RealmWidget 对象时插入计数为 1?
如果有人能解释这里发生了什么,我将不胜感激!
-- 编辑 --
我将相同的调试代码添加到我在 View Controller 中定义的观察 block 中,并注意到其他一些奇怪的东西。当这个“问题”发生时,我在调试控制台中看到这个输出:
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
所以我的 View Controller 中的观察 block 显示 1 个删除,但我的 AppDelegate 中的观察 block 显示 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>
在我的 View Controller 中没有以相同的方式对查询结果进行排序。
在我的 AppDelegate
, results
是所有 RealmWidget
的未排序集合 Realm 中的对象。但是在我的 View Controller 中,我用来定义 results
的辅助方法是所有 RealmWidgets
的排序集合 Realm 中的对象。
最佳答案
我通过 GitHub 将这个问题发布到 Realm 并得到了以下回复:
Yes, unsorted results are rearranged when objects are deleted. If you don't ask for an explicit sort order, then the objects are simply listed in the order that they happen to be stored on disk, and that is an unstable order that changes when objects are deleted.
We currently report the object at the end moving to the place of a deleted object as that object also being deleted and then inserted in the new location.
关于ios - 观察 Realm 结果集的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53211113/