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

Posted

技术标签:

【中文标题】NSPredicate 更改时不会触发领域通知【英文标题】:Realm Notification is not triggered when NSPredicate changes 【发布时间】:2016-11-22 21:48:49 【问题描述】:

我在 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。但是,即使修改了items 属性,更改self.includeAll 属性也不会触发通知。我可以在用户触发开关时包含self.tableView.reloadData(),但我希望通过通知获得更流畅的动画。

是我,谁把通知理解错了还是bug?

提前致谢!

【问题讨论】:

【参考方案1】:

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

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

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

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

最后一点。我可能没有足够的信息,所以这可能是不正确的,但是如果您在 items 属性上注册一个领域通知块,请注意您实现该 getter 的方式意味着生成了一个新对象每次调用它。将该属性标记为lazy 可能更合适,以便在第一次调用后保存。

【讨论】:

感谢您的回答,@TiM。 'tableView.reloadSections' 可以解决问题并且看起来比'tableView.reloadData' 更平滑。更改写入事务中的“includeAll”属性似乎并不能解决问题。我实际上希望“items.addNotificationBlock”能够监听“items”属性的变化,即使底层领域没有任何变化。 不用担心@Krabbas!很高兴我能帮上忙!啊,好吧。至少知道这一点很好。更改通知块会在底层 Realm 数据发生更改时做出响应,从而更改 Results 对象的内容。当与依赖外部属性的NSPredicate 复合时,它会变得更加复杂。

以上是关于NSPredicate 更改时不会触发领域通知的主要内容,如果未能解决你的问题,请参考以下文章

本地通知触发时更改图标徽章编号

更改 NSFetchedResultsController 的 fetchRequest.predicate 不会触发委托

领域快速通知停止触发

在后台应用程序时不会触发地理围栏通知

当我添加 NSPredicate 时,为啥我的 NSFetchedResultsController 委托停止触发?

如果在 iOS 设置中禁用通知访问时安排本地通知,则不会在 iOS 13 上触发本地通知