【问题标题】:@published not working with array of types, but works fine with single type@published 不适用于类型数组,但适用于单一类型
【发布时间】:2021-02-28 21:27:22
【问题描述】:

我正在测试非常简单的代码,有一个类确认@ObservableObject 协议,并且有两个@Published 属性,一个是我的自定义type 对象的数组,另一个只是普通的type同班。我有两种观点,父母持有单一事实来源,它有一个List 和一个navigationLink。 NavigationLink 正在将 @Published 数组对象作为 Binding 传递给 subView。

问题-:

当我输入TextField 时,视图没有更新。它正在修改@Published 对象属性,但不更新子视图。仅当我使用 Array 的对象进行测试时才会发生这种情况,但现在如果我评论 array 的对象属性并简单地使用另一个(不带数组),它会更新得很好。

谁能解释背后的原因,这是一个错误吗?还是Array 在幕后做其他事情?

不工作示例-:

import SwiftUI


struct Person: Identifiable {
    let id: String = UUID().uuidString
    var name: String = "Tushar"
    var age: Int = 25
    
    init(name: String,age: Int) {
        self.name = name
        self.age = age
    }
}

 class PersonStore: ObservableObject {
    @Published var name: [Person] = [Person(name:"foo",age:23),Person(name:"foobar",age:23)]
    //@Published var name: Person = Person(name:"foo",age:23)
}

struct ContentViewsss: View {
    
    @ObservedObject var store = PersonStore()
    
    @State var isEditing = false
    
    var body: some View {
        NavigationView{
            List(store.name.indices){ index in
                NavigationLink(destination: ContentViewsss1(store: $store.name[index])) {
                    Text("Edit")
                }
            }.navigationTitle(“Welcome")
        }
    }
}

struct ContentViewsss1: View {
    
    @Binding var store: Person

    var body: some View {
        TextField("My Text", text: $store.name)
        Text(store.name)
    }
}

工作示例-:

import SwiftUI


struct Person: Identifiable {
    let id: String = UUID().uuidString
    var name: String = "Tushar"
    var age: Int = 25
    
    init(name: String,age: Int) {
        self.name = name
        self.age = age
    }
}

 class PersonStore: ObservableObject {
   // @Published var name: [Person] = [Person(name:"foo",age:23),Person(name:"foobar",age:23)]
    @Published var name: Person = Person(name:"foo",age:23)
}

struct ContentViewsss: View {
    
    @ObservedObject var store = PersonStore()
    
    @State var isEditing = false
    
    var body: some View {
        NavigationView{
            List{ 
                NavigationLink(destination: ContentViewsss1(store: $store.name)) {
                    Text("Edit")
                }
            }.navigationTitle("Welcome")
        }
    }
}

struct ContentViewsss1: View {
    
    @Binding var store: Person

    var body: some View {
        TextField("My Text", text: $store.name)
        Text(store.name)
    }
}

【问题讨论】:

    标签: swiftui swiftui-navigationlink observableobject


    【解决方案1】:

    不是数组,也就是说,导致问题的不是数组——而是List。您会在原始代码中看到这一点,如果您将List 更改为ForEach,它将起作用。我不能确切地确定故障发生在哪里,而且它比人们想象的还要微妙。

    我的建议是使用中间视图模型。以下代码有效:

    class ViewModel: ObservableObject {
        @Published var person : Person {
            didSet {
                binding.wrappedValue = person
            }
        }
        var binding : Binding<Person>
        
        init(withPersonBinding person: Binding<Person>) {
            self.person = person.wrappedValue
            self.binding = person
        }
    }
    
    struct ContentViewsss1: View {
        //@Binding var store: Person
        @ObservedObject var store : ViewModel
        
        var body: some View {
            TextField("My Text", text: $store.person.name)
            Text(store.person.name)
        }
    }
    

    这样调用:

    NavigationLink(destination: ContentViewsss1(store: ViewModel(withPersonBinding: $store.name[index]))) {
       Text("Edit")
    }
    

    现在,真正奇怪的地方来了。如果您返回原始代码并将详细视图修改为:

    struct ContentViewsss1: View {
        
        @Binding var store: Person
        @State private var txt = ""
        
        var body: some View {
            TextField("My Text", text: $store.name)
            Text(store.name)
            TextField("Other text", text: $txt)
        }
    }
    

    您会看到,如果您编辑第一个文本字段,您的更改将不会反映(正如您所经历的那样)。 但是,一旦您更改第二个字段中的文本,@State 中的更改就会触发它也检查@Binding,并且该字段会更新。同样,这仅发生在List 而不是ForEach。 SwiftUI 的奥秘……

    【讨论】:

    • 我想当我将每个放在列表中时我也遇到了它,然后它也不起作用。这真的是 SwiftUi 的奥秘。但是,感谢您的建议解决方案。
    • 在我的测试列表中 { ForEach { } } 表现出这种行为,但单独的 ForEach 不会
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多