问题描述
绑定不符合预期并且 我很想了解正在发生的事情。
这是说明问题的代码。一个名为“Project”的类模型对象 包含一个名为“name”的字符串数组。 代码将 name 的 Binding 传递给 ProjectVM 类型的 viewmodel 在视图中使用。在视图列表中,我可以删除一行, 对应于删除字符串数组的元素之一, 但随后它又回来了。
这段代码应该在原始数组上运行,因为它是 使用绑定,但显然这不是正在发生的事情。有什么想法吗?
如果根对象是名称的@State var,它会按预期工作(请参阅 注释掉的代码)而不是项目的属性。
在 Swift 5 中使用 Xcode 12.4
@main
struct Try_ArrayBindingApp: App {
@State var project = Project()
//@State var names = [ "a","b","c" ]
var body: some Scene {
WindowGroup {
ProjectV(pVM: ProjectVM(names: $project.names))
//ProjectV(pVM: ProjectVM(names: $names))
}
}
}
class Project { var names = [ "one","two","three"] }
class ProjectVM: ObservableObject {
@Binding var names: [String]
init(names: Binding<[String]> ) { self._names = names }
func delete(at offsets: IndexSet) {
names.remove(atOffsets: offsets)
}
}
struct ProjectV: View {
@Observedobject var pVM: ProjectVM
var body: some View {
vstack {
List {
ForEach(pVM.names,id: \.self) { n in
Text(n)
}
.onDelete(perform: delete)
}
}
}
private func delete(at offsets: IndexSet) {
pVM.delete(at: offsets)
}
}
解决方法
通过在父视图中保存初始@State,然后将其@Binding 到 observable 对象,然后将其发送到子视图,至少,数据流肯定会变得混乱。我实际上并不相信它不应该表现得像你想象的那样,但这是一个令人困惑的思维模型,而不是你在 SwiftUI 中经常看到的东西。
更常见的模型是将状态保存在 ObservableObject 中,该对象归父视图所有:
@main
struct Try_ArrayBindingApp: App {
@StateObject var project = ProjectVM(names: [ "one","two","three"])
var body: some Scene {
WindowGroup {
ProjectV(pVM: project)
}
}
}
class ProjectVM: ObservableObject {
@Published var names: [String]
init(names: [String]) {
self.names = names
}
func delete(at offsets: IndexSet) {
names.remove(atOffsets: offsets)
}
}
struct ProjectV: View {
@ObservedObject var pVM: ProjectVM
var body: some View {
VStack {
List {
ForEach(pVM.names,id: \.self) { n in
Text(n)
}
.onDelete(perform: delete)
}
}
}
private func delete(at offsets: IndexSet) {
pVM.delete(at: offsets)
}
}
请注意,names
现在是 @Published
属性。