NSPredicate 更改时不会触发领域通知

Realm Notification is not triggered when NSPredicate changes

我在 Realm 中有一个简单的勾选列表,我在其中使用 NotificationToken 检查数据源中的更新,然后使用以下项目更新 tableView:

class Item : Object {
    dynamic var name = ""
    dynamic var isTickedOff = false
    dynamic var timeStamp : Date?
}

型号:

var items: Results<Item> {
    get {
        let results = self.realm.objects(Item.self)
        let alphabetic = SortDescriptor(property: "name", ascending: true)
        let tickedOff = SortDescriptor(property: "isTickedOff", ascending: true)
        let timestamp = SortDescriptor(property: "timeStamp", ascending: false)
        return results.sorted(by: [tickedOff, timestamp, alphabetic]).filter("isTickedOff = %@ || isTickedOff = %@", false, self.includeAll)
    }
}

我的表视图中有一个开关,用户可以在其中更改 self.includeAll 属性。

当插入、删除项目或选择它们时(导致将它们设置为 isTickedOff 或 !isTickedOff)触发通知并更新 tableView。但是,更改 self.includeAll 属性 不会触发通知,即使 items 属性 已修改。我可以在用户触发开关时包含 self.tableView.reloadData(),但我希望通知中的动画更流畅。

是我理解错了还是bug?

提前致谢!

Realm 不观察外部属性,因此它无法知道谓词查询中使用的 属性 何时发生更改,然后随后生成更改通知。

当您下次访问 items 时,这将为它提供足够的事件来重新计算内容,但到那时,它不会触发通知。

显然,正如您所说,最简单的解决方案是简单地调用 tableView.reloadData(),因为这将强制重新获取 items,但不会有动画。或者反过来,like this SO question says,你可以调用tableView.reloadSections来实际启用一个're-shuffling'动画。

最后,这可能是一个相当肮脏的 hack,但如果您仍然希望它触发基于 Realm 的更改通知,您可能只打开一个 Realm 写入通知,更改 includeAll 属性,然后关闭写入事务以尝试 'trick' Realm 执行更新。

最后一点要注意。我可能没有足够的信息,所以这可能是不正确的,但是如果你在 items 属性 之外注册一个 Realm 通知块,请注意你实现的方式 getter表示每次调用都会生成一个新的对象。将 属性 标记为 lazy 可能更合适,以便在第一次调用后保存。