I know there are similar questions out there, like this one for example Combining Predicate in SwiftData but all that looks unnecessary complex to me and I find it difficult to believe that there is no easier way.
This is what I need:
let aPred = #Predicate<Event> {
$0.dateStart != nil &&
($0.dateStart >= startOfDay && $0.dateStart <= endOfDay) ||
($0.dateEnd >= startOfDay && $0.dateEnd <= endOfDay) ||
($0.dateStart < startOfDay && $0.dateEnd >= startOfDay)
}
Event
is a SwiftData model which has 2 optional date properties dateStart
and dateEnd
which I need to compare against 2 dates startOfDay
and endOfDay
You probably know that this will give a compiling error:
The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions.
In Core Data we could easily do this with a single NSPredicate like this:
let nsPred = NSPredicate(format: "dateStart != nil && (dateStart >= %@ && dateStart <= %@) || (dateEnd >= %@ && dateEnd <= %@) || (dateStart < %@ && dateEnd >= %@)",
argumentArray: [startOfDay, endOfDay,
startOfDay, endOfDay,
startOfDay, startOfDay])
Or if needed, we could break that down into smaller predicates and then use NSCompoundPredicate
with .and or .or
There should be a simple way of achieving the same in SwiftData without all those complex macros, queries and predicate xpressions.
I have to keep each item optional as this is required by CloudKit.
Uploaded minimal working project here. See ViewController.swift.
This is because you are comparing an Optional<Date>
against a Date
.
Try to get rid of the optionality somehow like extending the Optional
, so it can be compared:
extension Optional: Comparable where Wrapped: Comparable {
public static func < (lhs: Wrapped?, rhs: Wrapped?) -> Bool {
guard let lhs, let rhs else { return false }
return lhs < rhs
}
}