You cannot use any instance member inside a Predicate so this shouldn't even compile
struct MyView: View {
@State private var selectedMonth: String = ""
// Instance member 'selectedMonth' cannot be used on type 'MyView'; did you mean to use a value of this type instead?
@Query(filter: #Predicate<Transaction> { $0.date.monthString == selectedMonth })
var transactions: [Transaction]
}
You can achieve what you want by putting your Query into a subview where you can provide a predicate or sort value using dependency injection.
struct ContainerView: View {
@State private var selectedMonth: String = ""
@State private var selectedYear: String = ""
var body: some View {
TransactionList(month: selectedMonth, year: selectedYear) // called every time your state properties change
.toolbar {
Menu { ... } // update your states values
}
}
}
struct TransactionList: View {
@Query private var transactions: [Transaction]
init(month: String, year: String) {
self._transactions = Query(filter: #Predicate<Transaction> {
$0.date.monthString == month && $0.date.yearString == year
}, sort: \.date)
}
}
For your information, you can retrieve SwiftData models by using FetchDescriptor.
let fetchDescriptor = FetchDescriptor<Transaction>(predicate: #Predicate { ... }, sortBy: [SortDescriptor(\.date)])
do {
let transactions = try modelContext.fetch(fechDescriptor)
} catch {
}
You can find more examples in the official documentation like Preserving your app’s model data across launches