ios - 观察 Realm 结果集的变化

标签 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对象插入数据库(这是从服务器接收数据的结果),我想在 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.

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

关于ios - 观察 Realm 结果集的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53211113/

相关文章:

swift - 如何(优雅地)将 Swift 枚举与关联值持久化——或者我应该避免它们?

iphone - 呈现 5 个选项且仍适合屏幕的最佳方式

ios - 将通过应用程序相机拍摄的照片与元数据一起保存到设备的相机胶卷

ios - 推送通知不适用于已签名的应用程序

iOS - 在 VIPER 模式上配置自定义 UITableViewCell

android - 在 android 中将 Realm 版本从 0.82.1 更改为 0.87.5 后发生致命异常崩溃

ios - 测试使用 Realm addNotificationBlock 的代码

ios - 我无法导入我需要的东西,以使用 MaterialContainerScheme

swift - 如何快速调用扩展中的函数?

通过实例方法设置时的 Swift Retain Cycle 问题