Is it possible to use a #Predicate that part of its expression calls a function (trying to pass that predicate into a SwiftData Query
):
func myPredicate(year: Int, month: Int) -> Predicate<MyObj> {
#Predicate<MyObj> { obj in
let components = Calendar.current.dateComponents([.year, .month], from: obj.date))
return components.year == year && components.month == month
}
}
In this case I'm getting an error that: Predicate body may only contain one expression
. I tried moving it to another static function like so:
extension MyObj {
static func checkDate(date: Date, year: Int, month: Month) {
let components = Calendar.current.dateComponents([.year, .month], from: obj.date))
return components.year == year && components.month == month
}
}
but now I'm getting The checkDate function is not supported in this predicate
Is there a way to do it, other than storing the date as a separate year and month fields?
Thanks
You can not call a function from the predicate, there is a list of what operations you can use in the documentation
Instead you can calculate a date interval from the given parameters and then use those date values in the predicate
static func predicate(year: Int, month: Int) -> Predicate<MyObj> {
let minDate = Calendar.current.date(from: DateComponents(year: year, month: month))!
let maxDate = Calendar.current.date(byAdding: .month, value: 1, to: minDate)!
return #Predicate<MyObj> { object in
object.date >= minDate && object.date < maxDate
}
}
(I am force unwrapping the calculated dates here but depending on how the input values has been validated you might want some better error handling)