Thursday, May 8, 2025

Optional Values in SwiftData Predicates

Fatbobman:

In the process of creating predicates for Core Data, the predicate expressions do not have a direct link to the type code. The properties used in these expressions correspond to those defined within the model editor (data model), and their “optional” characteristic does not align with the concept of optional types in Swift, but rather indicates whether the SQLite field can be NULL. This means that when a predicate expression involves a property that can be NULL and a non-NULL value, its optionality usually does not need to be considered.

[…]

However, the advent of SwiftData changes this scenario. Since the construction of SwiftData predicates is based on model code, the optional types therein truly embody the concept of optionals in Swift. This necessitates special attention to the handling of optional values when building predicates.

[…]

Although predicate construction in SwiftData is similar to writing a closure that returns a boolean value, developers can only use the operators and methods listed in the official documentation, which are converted into corresponding PredicateExpressions through macros.

He shows some examples of what you can do: somewhat surprisingly, introducing a new variable with if let works so long as you produce a single expression.

I really like optionals in general, but this is a case where I’m not sure we’re getting much value for the complexity. My recollection is that with Core Data the predicates just did the right thing without having to worry about this or to obscure the code with nil checks.

Even if a developer is certain a property is not nil, using ! to force unwrap in SwiftData predicates can still lead to runtime errors.

[…]

As of now (up to Xcode 15C500b), when the data model includes an optional to-many relationship, the methods mentioned above do not work. […] SwiftData encounters a runtime error when converting the predicate into SQL commands.

[…]

While there is no need for special handling in equality comparisons when an optional chain contains only one ?, situations involving multiple ?s in the chain, even though the code compiles and runs without errors, SwiftData cannot [prior to iOS 17.5] retrieve the correct results from the database through such a predicate.

Keith Harrison:

One other caveat. The #Predicate macro doesn’t handle accessing properties via a keypath.

[…]

The workaround is to introduce a temporary variable, outside of the macro, when constructing the predicate.

Previously:

Comments RSS · Twitter · Mastodon

Leave a Comment