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.