SwiftUI, как преобразовать элемент списка в подпредставление - PullRequest
0 голосов
/ 02 ноября 2019

Я пытался создать уменьшенное многоразовое представление для простого проекта SwiftUI. Однако я получаю неожиданные результаты и пытаюсь понять, почему.

Вот мой надуманный пример, чтобы выделить проблему

Используя этот пример, как создать повторно используемую RowView вместо 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 для запуска изменения модели. т.е. изменение оценки для прохождения или неудачи и ожидание того, что в подробном представлении списка будет отображено это изменение.

Вышеуказанный метод работает, как ожидалось, в то время как в представлении списка и строка изменяется при изменении данных.

Однако, когда я пытаюсь изменить вид, только один работает, как и ожидалось. В идеале я хотел бы передать объект 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")
        }
    }
}

Работа вокруг

// Allows me to pass in just the model
struct RowD: View {
    private var item = Grading()
    private var grade: String = ""
    private var pass: Bool = false

    init(item: Grading) {
        self.item = item
        self.grade = item.grade
        self.pass = item.pass
    }

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

Моя модель просмотра

class StudentGradingsUIViewModel: ObservableObject {
    @Published var detailedstudent: DetailedStudent

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

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

Ответы [ 2 ]

0 голосов
/ 02 ноября 2019

Это работает - интересно, я думаю, что это достойный подход

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)
    }
}
0 голосов
/ 02 ноября 2019

Если вы используете @state, я обнаружил, что все, что вы делаете, правильно, по крайней мере, в этой части View.

       / 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. часть.

...