SwiftUI如何将列表项重构为子视图

SwiftUI如何将列表项重构为子视图,swiftui,swiftui-list,Swiftui,Swiftui List,我一直在尝试为一个简单的SwiftUI项目创建更小的可重用视图。然而,我得到了出乎意料的结果,并且很难理解为什么 下面是我人为的例子来强调这个问题 使用此示例,您应该如何创建一个可重用的行视图来代替列表中的HStack var body: some View { List(vm.gradings) { item in // how should you refactor out this ?? HStack { Text(item.

我一直在尝试为一个简单的SwiftUI项目创建更小的可重用视图。然而,我得到了出乎意料的结果,并且很难理解为什么

下面是我人为的例子来强调这个问题

使用此示例,您应该如何创建一个可重用的行视图来代替列表中的
HStack

var body: some View {
    List(vm.gradings) { item in
        // how should you refactor out this ??
        HStack {
            Text(item.grade)
            Text(item.pass ? "Pass" : "Fail")
        }
    }
}
我正在使用Firebase触发模型更改。i、 e将等级更改为合格或不合格,并期望列表详细视图显示该更改

上述方法按预期工作,而在列表视图上,当数据更改时,行将更改

然而,当我尝试重构该视图时,只有一个视图按预期工作。理想情况下,我希望传入
Grading
对象,但这不会导致视图刷新

尝试不同的子视图及其结果

var body: some View {
    List(vm.gradings) { item in

        // Works
        RowA(grade: item.grade, pass: item.pass)

        // Fails
        // RowB(item: item)

        // Fails
        // RowC(item: item)

        // Default - works as expected
        // HStack {
        //  Text(item.grade)
        //  Text(item.pass ? "Pass" : "Fail")
        // }
    }
}
下面是3行选项

// Works
struct RowA: View {
    var grade: String
    var pass: Bool

    var body: some View {
        HStack {
            Text(grade)
            Text(pass ? "Pass" : "Fail")
        }
    }
}

// Fails
struct RowB: View {
    var item: Grading

    var body: some View {
        HStack {
            Text(item.grade)
            Text(item.pass ? "Pass" : "Fail")
        }
    }
}

// Fails
struct RowC: View {
    @State var item: Grading

    var body: some View {
        HStack {
            Text(item.grade)
            Text(item.pass ? "Pass" : "Fail")
        }
    }
}
变通

我的视图模型

class StudentGradingsUIViewModel: ObservableObject {
    @Published var detailedstudent: DetailedStudent

    var gradings: [Grading] {
        detailedstudent.student.gradings
    }

    init(student: DetailedStudent) {
        self.detailedstudent = student
    }
}

如果您使用@state,我发现您所做的一切至少在这些视图部分是正确的

       / Works
        struct RowA: View {
            var grade: String
            var pass: Bool

            var body: some View {
                HStack {
                    Text(grade)
                    Text(pass ? "Pass" : "Fail")
                }
            }
        }

        //// Fails
        struct RowB: View {
            var item: Grading

            var body: some View {
                HStack {
                    Text(item.grade)
                    Text(item.pass ? "Pass" : "Fail")
                }
            }
        }
        //
        //// Fails
        struct RowC: View {
            @State var item: Grading

            var body: some View {
                HStack {
                    Text(item.grade)
                    Text(item.pass ? "Pass" : "Fail")
                }
            }
        }

        struct  Grading: Identifiable{
            var id = UUID()
            var grade : String
            var pass  : Bool
        }

        struct TempGradingView: View {

            @State var gradings: [Grading] = [Grading.init(grade: "50", pass: false),Grading.init(grade: "100", pass: true),Grading.init(grade: "100", pass: true)]


        var body: some View {
            Group{
            Button("change", action: {
                self.gradings[0].grade = "70"
            })
            List(gradings) { item in

                // Works
               // RowA(grade: item.grade, pass: item.pass)

                // Fails
                 RowB(item: item)

                // Fails
                // RowC(item: item)

                // Default - works as expected
                // HStack {
                //  Text(item.grade)
                //  Text(item.pass ? "Pass" : "Fail")
                // }
                }}
        }
        }

因此,我认为有问题的部分,即@publisher var.part.

这是有效的-我想知道这是一个体面的方法

private func gradingRow(_ grading: Grading) -> some View {
    HStack {
        Text(grading.grade)
            .foregroundColor(grading.pass ? Color(UIColor.systemGreen) : Color(UIColor.systemRed))
        Spacer()
        Text(DateString.dateAsDDMMYYTime(from: grading.date))
            .font(.subheadline)
    }
}

理想的情况下,我只想通过项目。我确实找到了一种简单的方法来传递模型并让它刷新-我会发布你需要@publisher/和可观察的对象。我有这些-我想只是设置得不理想
private func gradingRow(_ grading: Grading) -> some View {
    HStack {
        Text(grading.grade)
            .foregroundColor(grading.pass ? Color(UIColor.systemGreen) : Color(UIColor.systemRed))
        Spacer()
        Text(DateString.dateAsDDMMYYTime(from: grading.date))
            .font(.subheadline)
    }
}