I have a simple Item model
@Model
class Item: Identifiable, Hashable {
@Attribute(.unique) let id = UUID()
var start: Date?
var end: Date?
var isEnded: Bool {
guard let end else { return false }
return end < Date.now
}
init(start: Date?, end: Date?) {
self.start = start
self.end = end
}
}
and a following view:
struct ItemsView: View {
@Query(
filter: #Predicate { $0.isEnded },
sort: [SortDescriptor(\Item.start)],
animation: .bouncy
)
private var items: [Item]
However there's a crash every time i try to fetch data.
Thread 1: Fatal error: Couldn't find \Item.isEnded on Item with fields [SwiftData.Schema.PropertyMetadata(name: "id", keypath: \Item.id, defaultValue: Optional(6EB32774-0C93-4DB6-B338-DBB534CAE1F4), metadata: Optional(Attribute - name: , options: [unique], valueType: Any, defaultValue: nil, hashModifier: nil)), SwiftData.Schema.PropertyMetadata(name: "start", keypath: \Item.start, defaultValue: nil, metadata: nil), SwiftData.Schema.PropertyMetadata(name: "end", keypath: \Item.end, defaultValue: nil, metadata: nil),
[...]
Can't computed properties be used to create predicate for @Query?
Computed properties can't be used in a query, the query is executed against the database so only stored properties are allowed.
You could write the predicate without the computed property though
private static var now: Date { Date.now }
@Query(filter: #Predicate {
if $0.end == nil {
return false
} else {
return $0.end! < now
}
}, sort: [SortDescriptor(\Item.start)], animation: .bouncy)
Note that we can't call Date.now
directly in the predicate but we can use a variable that contains the value instead.