realm / realm-swift

Realm is a mobile database: a replacement for Core Data & SQLite
https://realm.io
Apache License 2.0
16.32k stars 2.15k forks source link

Objects cannot be sorted by LinkingObjects/List.count #7294

Open bdkjones opened 3 years ago

bdkjones commented 3 years ago

Goals

I have an Realm Object that looks like this:

final class Foo: Object
{
    let myCollection: LinkingObjects<T> = [...]

    // Alternately, we could have this. Both LinkingObjects and List have the same problem:
    let myCollection: List<T> = [...]
}

I have a bunch of Foo objects in an NSTableView and I want to sort them by the count of myCollection. This is not possible. The following exception is raised:

Cannot sort on key path 'myCollection': property 'Foo.myCollection' is of unsupported type 'linking objects'.

This happens EVEN if I supply a custom NSSortDescriptor with a comparator:

 let usesSort = NSSortDescriptor(key: "myCollection", ascending: true) { obj1, obj2 in

            let count1: Int = (obj1 as! LinkingObjects<T>).count
            let count2: Int = (obj2 as! LinkingObjects<T>).count

            if count1 > count2 {
                return .orderedAscending
            } else if count1 < count2 {
                return .orderedDescending
            }
            return .orderedSame
        }

There is an issue over on Realm Java that's YEARS old about this very problem. (There's like 87 different Realm repos, so please feel free to move this report to wherever someone will actually act on it.)

Expected Results

LinkingObjects has a count property; it should support sorting by that property. The same is true for List<T>.

Actual Results

Because NSSortDescriptor cannot work with computed properties, it's not even possible to do something like:

    let myCollection: LinkingObjects<T> = [...]

    var myCollectionCount: Int {
        return myCollection.count
    }

The only solution is to keep a fully-independent count variable and then manually keep that count variable in sync when objects are added/removed from a LinkingObjects<T> or List<T>. That is....a glaring oversight.

Steps for others to Reproduce

See above

Code Sample

See above

Version of Realm and Tooling

Realm framework version: 10.7.7

RealmDatabase version: 10.7.2

Xcode version: 12.5

iOS/OSX version: 11.5

Dependency manager + version: SPM

bdkjones commented 3 years ago

It does appear that Realm is responsible for the exception:

Screen Shot 2021-06-16 at 18 00 41

dianaafanador3 commented 3 years ago

Hi @bdkjones Thanks for taking the time to report this, I'll take a look at it and try to reproduce. One question though, you mention this issue happens in Java, too? Or maybe I'm miss-reading this.

bdkjones commented 3 years ago

@dianaafanador3 There is an issue on the realm-Java repo asking for the same capability (sorting objects by the count of a List or LinkingObjects property). That issue is four years old. Thanks!

ironage commented 3 years ago

Related to https://github.com/realm/realm-java/issues/4501 and https://github.com/realm/realm-core/issues/4586 At this time, we only support sorting directly on properties, and not a computed value like the size of a list. We could potentially add support for it if there is demand though.

bdkjones commented 3 years ago

...There is demand.

I currently have extra countOfSomeStupidCollection properties strewn across my model objects just to support sorting. I have to keep these counts updated manually each time I change a List or Results or MutableSet. It's tedious.

To use Realm's default example, if we have a table like this:

| Owner Name              |  # of Dogs   |
------------------------------------------
| Alice                   |  2           |
| Bob                     |  10          |
| Chet                    |  7           |

And we want our user to be able to click the "# of Dogs" column header to sort the table, we have to keep a frivolous numberOfDogs property on Owner because we can't do this:

owners.sorted(byKeyPath: "dogs.count", ascending: true)

Other data persistence frameworks (Core Data) have supported this since their inception. I wasted a lot of time looking for functionality that didn't exist because I just assumed I had the syntax wrong—it couldn't be the case that Realm didn't support sorting by the count of a collection.