SwiftUI с Xcode 11 beta 7 не обновляет содержимое List / ForEach

Я пробовал простую функцию, чтобы добавить новые записи в список. Вид просто добавит новый сгенерированный. элемент (нет необходимости для ввода пользователем).

struct PeopleList: View {
@ObservedObject var people: PersonStore
var body: some View {
    NavigationView {
        VStack {
            Section {
                Button(action: add) {
                    Text("Add")
                }
            }
            Section {
                List {
                    ForEach(people.people) { person in

                        NavigationLink(destination: PersonDetail(person: person)) {
                            PersonRow(person: person)
                        }
                    }
                }
            }
        }
    }
    .navigationBarTitle(Text("People"))
    .listStyle(GroupedListStyle())
}

func add() {
    let newID = (people.people.last?.id ?? 0) + 1

    self.people.people.append(Person(id: newID, name: ""))
}
}

Раньше это работало в предыдущих бета-версиях, но по какой-то причине больше не работает. Когда я нажимаю на кнопку Добавить, приложение вызывает add() функция и добавляет новую запись в массив, но представление вообще не обновляется.

Это классы поддержки:

    class PersonStore: ObservableObject {

    var people: [Person] {
        willSet {
            willChange.send()
        }
    }

    init(people: [Person] = []) {
        self.people = people
    }

    var willChange = PassthroughSubject<Void, Never>()
}

class Person: ObservableObject, Identifiable {

    var id: Int = 0 {
        willSet {
            willChange.send()
        }
    }

    var name: String {
        willSet {
            willChange.send()
        }
    }

     init(id: Int, name: String) {
        self.id = id
        self.name = name
    }

    var willChange = PassthroughSubject<Void, Never>()
}

#if DEBUG

let data = [
    Person(id: 1, name: "David"),
    Person(id: 2, name: "Anne"),
    Person(id: 3, name: "Carl"),
    Person(id: 4, name: "Amy"),
    Person(id: 5, name: "Daisy"),
    Person(id: 6, name: "Mike"),
]

#endif

И поддержка просмотров:

struct PersonRow: View {

    @ObservedObject var person: Person

    var body: some View {
        HStack {
            Image(systemName: "\(person.id).circle")
            Text(person.name)
        }.font(.title)
    }
}

struct PersonDetail: View {

    @ObservedObject var person: Person

    var body: some View {
        HStack {

            Text("This is \(person.name)")
        }.font(.title)
    }
}

Я нашел кого-то с проблемой, которая выглядит немного связанной здесь: SwiftUI: Просмотр содержимого без перезагрузки, если @ObservedObject является подклассом UIViewController. Это ошибка или я что-то упустил? и здесь: SwiftUI @Binding не обновляет View

2 ответа

Решение

Проблема в том, что когда вы реализовали свой собственный ObservableObject, вы использовали не того издателя. Протокол ObservableObject создает издателя objectWillChange, но вы никогда не используете его, так что SwiftUI никогда не информируется о том, что что-то изменилось.


class Person: ObservableObject, Identifiable {
    let id: Int

    @Published
    var name: String

    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }
}

Я не запускал это через компилятор, поэтому могут быть некоторые опечатки.

Вам не нужно использовать @Published, но для простого случая, подобного вашему, это проще. Конечно, вам нужно обновить и другой класс.

Еще одна маленькая вещь, идентификатор требуется никогда не менять, List et al. используйте его, чтобы связать ваши данные с представлением, которое они создают.

Person должен быть типом значения, система наблюдений SwiftUI работает только с типами значений. Затем создайте класс PersonStore, который соответствует протоколу ObservableObject.

Другие вопросы по тегам