观察Realm结果集的变化

时间:2018-11-08 15:37:55

标签: ios swift 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对象时(由于从服务器接收数据而发生),我想在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

关于这件事我不清楚:

  • 当我仅删除一个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-

此行为似乎与以下事实有关:我的AppDelegate中的Results<RealmWidget>和视图控制器中的Results<RealmWidget>并非以相同的方式对查询结果进行排序。

在我的AppDelegate中,results是领域中所有RealmWidget对象的未排序集合。但是在我的视图控制器中,我用来定义results的辅助方法是领域中所有RealmWidgets对象的 sorted 集合。

1 个答案:

答案 0 :(得分:0)

我通过GitHub将这个问题发布到Realm并得到了以下回复:

  

是的,删除对象时会重新排列未排序的结果。如果你   不要要求明确的排序顺序,那么对象就是   以它们恰好存储在磁盘上的顺序列出,即   删除对象后会改变的不稳定顺序。

     

我们当前报告对象移到末尾的位置   删除的对象,因为该对象也将被删除然后插入   新位置。

https://github.com/realm/realm-cocoa/issues/6130