Xcode 11 beta 7 的 SwiftUI 不更新 List/ForEach 的内容
SwiftUI with Xcode 11 beta 7 not updating contents of 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: View content not reloading if @ObservedObject is a subclass of UIViewController. Is this a bug or am I missing something?
和这里:
问题在于,当您实现自己的 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,但对于像您这样的简单案例,它更容易。当然,您还需要更新其他 class。
另外一件小事,要求id永不改变,List等。使用它将您的数据与他们创建的视图联系起来。
我一直在尝试一个简单的功能来将新条目添加到列表中。视图只会添加一个新生成的。项目(无需用户输入)。
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: View content not reloading if @ObservedObject is a subclass of UIViewController. Is this a bug or am I missing something?
和这里:
问题在于,当您实现自己的 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,但对于像您这样的简单案例,它更容易。当然,您还需要更新其他 class。
另外一件小事,要求id永不改变,List等。使用它将您的数据与他们创建的视图联系起来。