I receive the below error when trying to init a SwiftData query in a view:
Error: Cannot convert value of type 'PredicateExpressions.Equal<PredicateExpressions.KeyPath
<PredicateExpressions.Variable<Array<Todo>.Element>, Int>, PredicateExpressions.KeyPath<PredicateExpressions.Value<Section>,
Int>>'(aka'PredicateExpressions.Equal<PredicateExpressions.
KeyPath<PredicateExpressions.Variable<Todo>, Int>, PredicateExpressions.KeyPath<PredicateExpressions.Value<Section>,
Int>>') to closure result type 'any StandardPredicateExpression<Bool>'
TodoView.swift
import SwiftUI
import SwiftData
struct TodoView: View {
@Query var todos: [Todo]
@EnvironmentObject var currentSection: Section
@Environment(\.modelContext) var modelContext
var DWMY = ["D","W","M","Y"]
var body: some View {
List {
ForEach(todos) { todo in
HStack {
if todo.completed == false {
Text("[ ]")
} else {
Text("[X]")
}
Text(todo.name)
Text(DWMY[todo.section])
}
}
.onDelete(perform: deleteToDo)
}
.navigationBarTitleDisplayMode(.inline)
}
init(todoSection: Section) {
_todos = Query(filter: #Predicate { todo in
todo.section == currentSection.section
})
}
func deleteToDo(at offsets: IndexSet ) {
for offset in offsets {
let todo = todos[offset]
modelContext.delete(todo)
}
}
}
The error occurs when I try to give the query the value currentSection.section
if I replace currentSection.section
with a hard coded Int there are no errors.
From what I have read this is happening because my Environment is not passed down to ToDoView.swift
until Body is created so currentSection.section
does not exist when init
occurs.
What is the correct way to pass my currentSection.section
value into init
?
I would make TodoView
not depend on the environment object for creating the Query
. Have the init
take in the section number.
struct TodoView: View {
@Query var todos: [Todo]
// you could still have the EnvironmentObject here for other purposes, just not for creating the query
// @EnvironmentObject var currentSection: Section
init(sectionNumber: Int) {
_todos = Query(filter: #Predicate { todo in
todo.section == sectionNumber
})
}
var body: some View {
List(todos) { todo in
Text(todo.name)
// ...
}
}
}
Then get the EnvironmentObject
in the parent view:
struct TodoWrapper: View {
@EnvironmentObject var currentSection: Section
var body: some View {
TodoView(sectionNumber: currentSection.section)
}
}