ForEach 不使用 Identifiable & id = UUID()
ForEach not working with Identifiable & id = UUID()
import SwiftUI
struct TestStudentView: View {
@StateObject var students = Students()
@State private var name = ""
@State private var numberOfSubjects = ""
@State private var subjects = [Subjects](repeating: Subjects(name: "", grade: ""), count: 10)
var body: some View {
NavigationView {
Group {
Form {
Section(header: Text("Student details")) {
TextField("Name", text: $name)
TextField("Number of subjects", text: $numberOfSubjects)
}
let count = Int(numberOfSubjects) ?? 0
Text("Count: \(count)")
Section(header: Text("Subject grades")) {
if count>0 && count<10 {
ForEach(0 ..< count, id: \.self) { number in
TextField("Subjects", text: $subjects[number].name)
TextField("Grade", text: $subjects[number].grade)
}
}
}
}
VStack {
ForEach(students.details) { student in
Text(student.name)
ForEach(student.subjects) { subject in //Does not work as expected
//ForEach(student.subjects, id:\.id) { subject in //Does not work as expected
//ForEach(student.subjects, id:\.self) { subject in //works fine with this
HStack {
Text("Subject: \(subject.name)")
Text("Grade: \(subject.grade)")
}
}
}
}
}
.navigationTitle("Student grades")
.navigationBarItems(trailing:
Button(action: {
let details = Details(name: name, subjects: subjects)
students.details.append(details)
}, label: {
Text("Save")
})
)
}
}
}
struct TestStudentView_Previews: PreviewProvider {
static var previews: some View {
TestStudentView()
}
}
class Students: ObservableObject {
@Published var details = [Details]()
}
struct Details: Identifiable {
let id = UUID()
var name: String
var subjects: [Subjects]
}
struct Subjects: Identifiable, Hashable {
let id = UUID()
var name: String
var grade: String
}
当我使用 - "ForEach(student.subjects, id:.id) { subject in" 时,正常情况下应该是 id = UUID,错误的输出如下:
然后,由于 class 符合 Identifiable 我试过 - "ForEach(student.subjects) { subject in" 它仍然无法正常工作。但是,当我这样做时 - "ForEach(student.subjects, id:.self) { subject in" 除了我必须让 class 符合 hashable 并给我正确的预期输出。显示的正确输出:
您需要使用地图而不是重复。
通过使用 Array.init(repeating:) 将仅调用 Subjects 初始化一次,然后多次将该对象插入到数组中。
所以,在这种情况下,所有 id 都是相同的。
你可以通过这个 .onAppear() { print(subjects.map({ (sub) in print(sub.id) }))
打印所有的 id 来检查
struct TestStudentView: View {
@StateObject var students = Students()
@State private var name = ""
@State private var numberOfSubjects = ""
@State private var subjects: [Subjects] = (0...10).map { _ in
Subjects(name: "", grade: "")
} //<-- Here
import SwiftUI
struct TestStudentView: View {
@StateObject var students = Students()
@State private var name = ""
@State private var numberOfSubjects = ""
@State private var subjects = [Subjects](repeating: Subjects(name: "", grade: ""), count: 10)
var body: some View {
NavigationView {
Group {
Form {
Section(header: Text("Student details")) {
TextField("Name", text: $name)
TextField("Number of subjects", text: $numberOfSubjects)
}
let count = Int(numberOfSubjects) ?? 0
Text("Count: \(count)")
Section(header: Text("Subject grades")) {
if count>0 && count<10 {
ForEach(0 ..< count, id: \.self) { number in
TextField("Subjects", text: $subjects[number].name)
TextField("Grade", text: $subjects[number].grade)
}
}
}
}
VStack {
ForEach(students.details) { student in
Text(student.name)
ForEach(student.subjects) { subject in //Does not work as expected
//ForEach(student.subjects, id:\.id) { subject in //Does not work as expected
//ForEach(student.subjects, id:\.self) { subject in //works fine with this
HStack {
Text("Subject: \(subject.name)")
Text("Grade: \(subject.grade)")
}
}
}
}
}
.navigationTitle("Student grades")
.navigationBarItems(trailing:
Button(action: {
let details = Details(name: name, subjects: subjects)
students.details.append(details)
}, label: {
Text("Save")
})
)
}
}
}
struct TestStudentView_Previews: PreviewProvider {
static var previews: some View {
TestStudentView()
}
}
class Students: ObservableObject {
@Published var details = [Details]()
}
struct Details: Identifiable {
let id = UUID()
var name: String
var subjects: [Subjects]
}
struct Subjects: Identifiable, Hashable {
let id = UUID()
var name: String
var grade: String
}
当我使用 - "ForEach(student.subjects, id:.id) { subject in" 时,正常情况下应该是 id = UUID,错误的输出如下:
然后,由于 class 符合 Identifiable 我试过 - "ForEach(student.subjects) { subject in" 它仍然无法正常工作。但是,当我这样做时 - "ForEach(student.subjects, id:.self) { subject in" 除了我必须让 class 符合 hashable 并给我正确的预期输出。显示的正确输出:
您需要使用地图而不是重复。
通过使用 Array.init(repeating:) 将仅调用 Subjects 初始化一次,然后多次将该对象插入到数组中。
所以,在这种情况下,所有 id 都是相同的。
你可以通过这个 .onAppear() { print(subjects.map({ (sub) in print(sub.id) }))
struct TestStudentView: View {
@StateObject var students = Students()
@State private var name = ""
@State private var numberOfSubjects = ""
@State private var subjects: [Subjects] = (0...10).map { _ in
Subjects(name: "", grade: "")
} //<-- Here