2

My model has an GroupOfEvents realm object that has a to-many relationship to Event realm object via the property events. Each Event has a date property.

I have a Results<GroupOfEvents> and I want to sort by the date of the first event in events. If I were sorting a regular swift array, it would look like:

groupsOfEvents.sorted(by: { $0.events.first!.date > $1.events.first!.date })

Here is my failed attempt to sort a Results<GroupOfEvents>:

groupsOfEvents.sorted(byKeyPath: "events.first.date")

It gives the error:

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

How can I sort it the way I want?


Questions you might ask me:

Why are you sorting by the first event's date? That's not something people usually do.

In fact, GroupOfEvents contains events with the same date, so using the date of any event in events will work.

Why don't you just move the date property to GroupOfEvents?

Yes, I could do that, but I am looking for alternatives to that.

Why don't you get rid of GroupOfEvents and just get all the Events then group by the date?

Although all events in a GroupOfEvents have the same date. The events of two different GroupOfEvents can have the same date as well. There are other properties that differentiates GroupOfEvents.

Sweeper
  • 213,210
  • 22
  • 193
  • 313

3 Answers3

0

From Realm's header files I see this comment:

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

That means that your array of events is not a supported key-path, just as the error you are receiving is saying.

Update

Based on this answer you can cast an object of type Results to an array. So you could try something along these lines:

let groupsOfEventsSortedArray = Array(groupsOfEvents).sorted { $0.events.first!.date > $1.events.first!.date }
Mihai Fratu
  • 7,579
  • 2
  • 37
  • 63
0

For now, you can't do that. It should be describe in any "realm limitation list", but it doesn't. In fact, there is an issue on github for this problem: Support of keypath sorting for to-many relationships.

And here is some workaround about the problem:

  1. The best solution will be to add firstEvent: Event to GroupOfEvents model. The Support sorting by keypath says, that you can sort by .sorted(byKeyPath: "firstEvent.date"). But it introduces extra work to sync the firstEvent and events.first.

  2. The cheapest way for programmer and potentially the worst for efficiency - cast to Array and then sort. Very simple, but as you know realm gives you object only when you start working with it (i.e. they place lazy everywhere they can). If you haven't a big amount of data - this should works well.


Also, Realm has nice NSPredicate Cheatsheet, that covers useful patterns and mark supported cases by pink dot.

pacification
  • 5,838
  • 4
  • 29
  • 51
0

I am not sure if I understand the question correctly, but the Results class has asorted function that accepts a Sequence (see the documentation). Hence, you can just do the following:

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)
TmKVU
  • 2,910
  • 2
  • 16
  • 30