ForEach 不使用 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 工作,错误输出如下:

enter image description here

然后当类符合 Identifiable 我试过 - “ForEach(student.subjects) { subject in”它仍然不能正常工作。但是,当我这样做时 - “ForEach(student.subjects,id:.self) { subject in” 除非我必须让类符合 hashable 并给我正确的预期输出显示的正确输出

enter image description here

解决方法

您需要使用地图而不是重复。

使用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