realm / realm-swift

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

Swift High Order Filter on EmbeddedObject Fails #7491

Closed Jaycyn closed 2 years ago

Jaycyn commented 2 years ago

How frequently does the bug occur?

All the time

Description

Using a Swift High Order function, like filter, map or reduce, works on Realm Objects. However, it does not appear to work on EmbeddedObjects

Stacktrace & log output

No response

Can you reproduce the bug?

Yes, always

Reproduction Steps

Start with a Person object with a List of embedded dogs, with each dog having an age property

class Person: Object {
   let dogs = List<EmbeddedDog>()
}
class EmbeddedDog: EmbeddedObject {
     @Persisted var age = 0
}

and suppose there are 3 dogs embedded in a persons dogs list with ages 1, 2 and 3.

Using a regular Realm filter, this works

let results = person.dogs.filter("age > 1")

and returns dogs with ages 2 and 3. Wheras if a Swift High Order filter is used, it does not work...

{{let results = person.dogs.filter { $0.age > 1 }}}

returns all of the dogs in the list.

By comparison, if the List contains a regular, non embedded dog object

class Person: Object {
   let dogs = List<Dog>()
}
class Dog: Object {
   @Persisted var age = 0
}

this Swift High Order filter works correctly, and returns dogs with ages 2 and 3

{{let results = person.dogs.filter { $0.age > 1 }}}

Version

10.7 and higher

What SDK flavour are you using?

Local Database only

Are you using encryption?

No, not using encryption

Platform OS and version(s)

macOS 10.14 and above

Build environment

Xcode version: ... 11.3.1 and above Dependency manager and version: ... CocoaPods 1.10.1 and above

leemaguire commented 2 years ago

.filter will return a LazyFilterSequence unless you specify [EmbeddedDog] as the return type. e.g

let notLazy: [EmbeddedDog] = person.dogs.filter { $0.age > 1 }

The above will evaluate the result immediately.

A LazyFilterSequence will be evaluated when it is used. For example calling .first or doing a for loop will grant you the correct results.

Jaycyn commented 2 years ago

@leemaguire You are correct.

I am not sure what circumstances was causing the issue but a clean and rebuild corrected it.