我正在使用使用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
对象时(由于从服务器接收数据而发生),我想在UI中的UITabBar
上显示徽章。该代码似乎正常工作。
在我的应用程序的另一部分,我有一个带有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
关于这件事我不清楚:
如果任何人都可以解释这里发生的事情,我将不胜感激!
-编辑-
我将相同的调试代码添加到了视图控制器内部定义的观察块中,并发现了其他奇怪的地方。当出现“问题”时,我会在调试控制台中看到以下输出:
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-
此行为似乎与以下事实有关:我的AppDelegate中的Results<RealmWidget>
和视图控制器中的Results<RealmWidget>
并非以相同的方式对查询结果进行排序。
在我的AppDelegate
中,results
是领域中所有RealmWidget
对象的未排序集合。但是在我的视图控制器中,我用来定义results
的辅助方法是领域中所有RealmWidgets
对象的 sorted 集合。
答案 0 :(得分:0)
我通过GitHub将这个问题发布到Realm并得到了以下回复:
是的,删除对象时会重新排列未排序的结果。如果你 不要要求明确的排序顺序,那么对象就是 以它们恰好存储在磁盘上的顺序列出,即 删除对象后会改变的不稳定顺序。
我们当前报告对象移到末尾的位置 删除的对象,因为该对象也将被删除然后插入 新位置。