Realm: Predicate Returning Lazyfiltercollection - How to Convert to Results<T>

Filter by date component in Realm

Unfortunately it's not that simple. Results.filter takes nspredicate or a predicate format string.

let trainingsBetweenDates = realm.objects(Trainings.self).filter("date BETWEEN {%@, %@}", startDate, endDate)

you can make the boundary dates yourself using the methods described here:How do you create a swift Date object

LazyFilterBidirectionalCollectionResultsdatatype' to expected argument type '[datatype]'

filter, map, etc. are lazy operations on the Results returned by objects. This is implemented in types such as LazyFilterBidirectionalCollection<T>. To actually perform the filtering and get an array of results, you need to promote this collection to an array by wrapping in an Array initializer (e.g. Array(bgRealm.objects...))

From the docs:

Queries return a Results instance, which contains a collection of
Objects. Results have an interface very similar to Array and objects
contained in a Results can be accessed using indexed subscripting.
Unlike Arrays, Results only hold Objects of a single subclass type.
All queries (including queries and property access) are lazy in Realm.
Data is only read when the properties are accessed.

Cannot convert return expression of type 'LazyFilterBidirectionalCollection'

Swift is deferring the creation of an array for efficiency's sake. Instead of giving you an Array, it is providing you with a LazyFilterBidirectionalCollection which is a lazy Collection wrapper that includes the elements of an underlying collection that satisfy a predicate. In your case, it is the Realm elements that satisfy the closure you passed to filter. Lazy means that the values are pulled from Realm as you access them instead of all at once. A Collection is a protocol that conforms to Sequence and Indexable. A Sequence is a type that provides sequential, iterated access to its elements. So, at its most basic level, LazyFilterBidirectionalCollection is a sequence.

There is an initializer for Array that converts a Sequence into an array:

init<S : Sequence where S.Iterator.Element == Element>(_ s: S)

Since you need to return a real array

replace:

return emptyEntryModels

with:

return Array(emptyEntryModels)

That will make a proper array from the LazyFilterBidirectionalCollection.


Other examples of using this Array initializer to convert a sequence into an array:

let digits = Array(0...9)                             // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
let odds = Array(stride(from: 1, through: 9, by: 2)) // [1, 3, 5, 7, 9]


Related Topics



Leave a reply



Submit