如何根据一对多关系中第一项的键路径对 Realm 结果进行排序?

How do I sort Realm Results by a keypath of the first item in a to-many relationship?

我的模型有一个 GroupOfEvents 领域对象,它通过 属性 eventsEvent 领域对象具有一对多关系。每个 Event 都有一个 date 属性.

我有一个 Results<GroupOfEvents>,我想按 events 中第一个事件的 date 排序。如果我对常规 swift 数组进行排序,它看起来像:

groupsOfEvents.sorted(by: { [=10=].events.first!.date > .events.first!.date })

这是我对 Results<GroupOfEvents>:

排序失败的尝试
groupsOfEvents.sorted(byKeyPath: "events.first.date")

它给出了错误:

'Cannot sort on key path 'events.first.date': property 'GroupOfEvents.events' is of unsupported type 'array'.'

我怎样才能按我想要的方式排序?


你可能会问我的问题:

为什么要按第一个事件的日期排序?人们通常不会这样做。

事实上,GroupOfEvents 包含具有相同日期的事件,因此使用 events 中任何事件的日期都可以。

为什么不把 date 属性 移到 GroupOfEvents

是的,我可以做到,但我正在寻找替代方法。

你为什么不去掉 GroupOfEvents 而只获取所有 Events 然后按日期分组?

尽管 GroupOfEvents 中的所有 events 具有相同的日期。两个不同 GroupOfEvents 的事件也可以具有相同的日期。还有其他区分 GroupOfEvents.

的属性

从 Realm 的头文件中我看到了这条评论:

Collections may only be sorted by properties of boolean, Date, NSDate, single and double-precision floating point, integer, and string types.

这意味着您的事件数组不是受支持的键路径,正如您收到的错误所说的那样。

更新

根据 的回答,您可以将 Results 类型的对象转换为数组。所以你可以尝试以下方法:

let groupsOfEventsSortedArray = Array(groupsOfEvents).sorted { [=10=].events.first!.date > .events.first!.date }

目前,您不能这样做。它应该在任何 "realm limitation list" 中描述,但它没有。其实这个问题在github上有个issue:Support of keypath sorting for to-many relationships.

下面是解决该问题的一些方法:

  1. 最佳解决方案是将 firstEvent: Event 添加到 GroupOfEvents 模型。 Support sorting by keypath 表示,您可以按 .sorted(byKeyPath: "firstEvent.date") 排序。但是它引入了额外的工作来同步 firstEventevents.first.

  2. 对程序员来说成本最低但效率可能最差的方法 - 转换为 Array 然后排序。非常简单,但正如您所知,只有当您开始使用它时,领域才会为您提供对象(即,他们将 lazy 放置在任何地方)。如果您没有大量数据 - 这应该很有效。


另外,Realm 有很好的 NSPredicate Cheatsheet,它涵盖了有用的模式并用粉色点标记支持的案例。

我不确定我是否理解正确的问题,但是 Results class 有一个 sorted 函数接受 Sequence (见 documentation).因此,您只需执行以下操作:

func sortGroupOfEvents(e1: GroupOfEvents, e2: GroupOfEvents) -> Bool{
    guard let date1 = e1.events.first?.date else {return false}
    guard let date2 = e2.events.first?.date else {return true}
    return date1 > date2
}

groupsOfEvents.sorted(by: sortGroupOfEvents)