I am new to the Swift and the SwiftUI. Trying to understand how sorting works on SwiftUI Table view.
The following code does what I intend to do, but I am not able to understand how does it actually work with multiple key path. Need help with the answers for the questions posted below the code.
// MARK: - Student Model
struct Student: Codable, Identifiable {
let id: String
let name: String
let gradeHistory: GradeHistory
enum CodingKeys: String, CodingKey {
case id, name
case gradeHistory = "grade_history"
}
}
// MARK: - GradeHistory Model
struct GradeHistory: Codable, Identifiable{
let id: String?
let semester: String
let subjects: Subjects
init(
id: String? = UUID().uuidString,
semester: String,
subjects: Subjects
) {
self.id = id ?? UUID().uuidString
self.semester = semester
self.subjects = subjects
}
}
// MARK: - Subjects Model
struct Subjects: Codable, Identifiable {
let id: String?
let math: Int
let science: Int
let english: Int
let physics: Int
let computer: Int
let socialScience: Int
init(
id: String? = nil,
math: Int,
science: Int,
english: Int,
physics: Int,
computer: Int,
socialScience: Int
) {
self.id = id ?? UUID().uuidString
self.math = math
self.science = science
self.english = english
self.physics = physics
self.computer = computer
self.socialScience = socialScience
}
enum CodingKeys: String, CodingKey {
case id = "id"
case math = "Math"
case science = "Science"
case english = "English"
case physics = "Physics"
case computer = "Computer"
case socialScience = "Social Science"
}
}
let _students: [Student] = [
Student(
id: "S001",
name: "John Doe",
gradeHistory: GradeHistory(
semester: "Fall 2022",
subjects: Subjects(
math: 85,
science: 78,
english: 90,
physics: 88,
computer: 95,
socialScience: 80
)
)
),
Student(
id: "S002",
name: "Jane Smith",
gradeHistory: GradeHistory(
semester: "Spring 2023",
subjects: Subjects(
math: 92,
science: 85,
english: 89,
physics: 91,
computer: 94,
socialScience: 88
)
)
),
Student(
id: "S003",
name: "Emily Johnson",
gradeHistory: GradeHistory(
semester: "Fall 2023",
subjects: Subjects(
math: 78,
science: 81,
english: 82,
physics: 86,
computer: 90,
socialScience: 84
)
)
)
]
struct StudentGradeHistoryView: View {
@State var students = _students
@State private var sortOrder = [KeyPathComparator(\Student.name)]
var body: some View {
NavigationStack {
Table(students,
selection: students.selectedStudents,
sortOrder: $sortOrder) {
TableColumn("Index") { student in
let index = (students.firstIndex(
where: { $0.id == student
.id }) ?? 0)
Text("No. \(index + 1)")
}
TableColumn("Id", value: \.id)
TableColumn("Name", value: \.name)
.width(min: 150)
TableColumn("Math") { student in
Text("\(student.gradeHistory.subjects.math)")
.foregroundStyle(
gradeColor(for: student.gradeHistory.subjects.math)
)
}
.defaultVisibility(.automatic)
TableColumn("Science") { student in
Text("\(student.gradeHistory.subjects.science)")
.foregroundStyle(gradeColor(for: student.gradeHistory.subjects.science))
}
TableColumn("English") { student in
Text("\(student.gradeHistory.subjects.english)")
.foregroundStyle(gradeColor(for: student.gradeHistory.subjects.english))
}
TableColumn("Physics") { student in
Text("\(student.gradeHistory.subjects.physics)")
.foregroundStyle(gradeColor(for: student.gradeHistory.subjects.physics))
}
TableColumn("Computer") { student in
Text("\(student.gradeHistory.subjects.computer)")
.foregroundStyle(gradeColor(for: student.gradeHistory.subjects.computer))
}
TableColumn("Social Science") { student in
Text("\(student.gradeHistory.subjects.socialScience)")
.foregroundStyle(gradeColor(for: student.gradeHistory.subjects.socialScience))
}
}
.onChange(of: sortOrder) {
students.sort(using: sortOrder)
}
}
}
}
My question is how I can use KeyPathComparator
in this model to sort data with multiple comparator paths like
@State private var sortOrder = [
KeyPathComparator(\Student.name),
KeyPathComparator(\Subjects.math)
]
It's not working if i user this sortOrder
.
I was expectin that each table column should be sortable but i don't know why different KeyPathCoparator is not working.
The problem is that you are not using an init for TableColumn
that supports sorting, see the documentation for all alternatives but here is one example of making the math column sortable
TableColumn("Math Sortable", value: \.gradeHistory.subjects.math) {
Text("\($0.gradeHistory.subjects.math)")
}
and with that you can now get correct sorting from the start
@State private var sortOrder = [
KeyPathComparator(\Student.name),
KeyPathComparator(\Student.gradeHistory.subjects.math)
]