Overview
- I have 2 models:
Deparment
andStudent
- Each
Department
can contain multiple students - Each
Student
can only be in oneDepartment
- I have
DepartmentList
, tapping on the department should take it to theStudentList
which lists all students in the department
Problem
- When I use Query in
StudentList
to filter only students for a specific department id, no students are shown.
Questions:
What should I do to list the students in a department? (see complete code below).
let filter = #Predicate<Student> { student in
student.department?.id == departmentID
}
let query = Query(filter: filter, sort: \.name)
_students = query
Complete code
App
@main
struct SchoolApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(for: [Department.self, Student.self])
}
}
Department
import Foundation
import SwiftData
@Model
class Department {
var id: UUID
var name: String
var students: [Student]
init(
id: UUID,
name: String,
students: [Student] = []
) {
self.id = id
self.name = name
self.students = students
}
}
Student
import Foundation
import SwiftData
@Model
class Student {
var id: UUID
var name: String
@Relationship(inverse: \Department.students)
var department: Department?
init(
id: UUID,
name: String,
department: Department? = nil
) {
self.id = id
self.name = name
self.department = department
}
}
ContentView
import SwiftUI
struct ContentView: View {
@State private var selectedDepartment: Department?
var body: some View {
NavigationSplitView {
DepartmentList(selectedDepartment: $selectedDepartment)
} detail: {
if let department = selectedDepartment {
StudentList(department: department)
} else {
Text("no department selected")
}
}
.task {
printStoreFilePath()
}
}
private func printStoreFilePath() {
let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
if let path = urls.map({ $0.path(percentEncoded: false) }).first {
print("Storage: \(path)")
}
}
}
DepartmentList
import SwiftUI
import SwiftData
struct DepartmentList: View {
@Binding
var selectedDepartment: Department?
@Query(sort: \.name)
private var departments: [Department]
@Environment(\.modelContext)
private var modelContext
var body: some View {
List(selection: $selectedDepartment) {
ForEach(departments) { department in
NavigationLink(value: department) {
Text(department.name)
}
}
}
.toolbar {
ToolbarItem {
Button {
addDepartment()
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
private func addDepartment() {
guard let index = (1000..<10000).randomElement() else {
return
}
let department = Department(id: UUID(), name: "Department \(index)")
modelContext.insert(department)
}
}
StudentList
import SwiftUI
import SwiftData
struct StudentList: View {
var department: Department
@Query
private var students: [Student]
@Environment(\.modelContext)
private var modelContext
init(department: Department) {
self.department = department
let departmentID = department.id
let filter = #Predicate<Student> { student in
student.department?.id == departmentID
}
let query = Query(filter: filter, sort: \.name)
_students = query
}
var body: some View {
List {
ForEach(students) { student in
Text(student.name)
}
}
.toolbar {
ToolbarItem {
Button {
addStudent()
} label: {
Label("Add", systemImage: "plus")
}
}
}
}
private func addStudent() {
guard let index = (1000..<10000).randomElement() else {
return
}
let student = Student(
id: UUID(),
name: "Student \(index)",
department: department
)
modelContext.insert(student)
}
}