【问题标题】:SwiftUI update data for parent NavigationView父 NavigationView 的 SwiftUI 更新数据
【发布时间】:2020-06-27 16:53:32
【问题描述】:

如何更新位于 NavigationView 细节中的 TextField 中的数据?我希望在父视图的列表中更新数据。这是我的代码:

class Address: ObservableObject, Identifiable {
    let id = UUID()
    @Published var name: String
    @Published var age: String
    
    init(name: String, age: String) {
        self.name = name
        self.age = age
    }
}
class AddressBook: ObservableObject {
    @Published var addresses: [Address]

    init(addresses: [Address]) {
        self.addresses = addresses
    }
}
struct TestData {
    static let addressbook = AddressBook(addresses: [
        Address(name: "Person1", age: "39"),
        Address(name: "Person2", age: "22")
    ])
}
struct ContentView: View {
    @ObservedObject var addressbook = TestData.addressbook
    
    var body: some View {
        NavigationView {
            List (addressbook.addresses) {address in
                NavigationLink(destination: AddressDetail(address: address)) {
                    Text(address.name)
                }
            }
            .navigationBarTitle("Addressbook")
        }
        
    }
}

struct AddressDetail: View {
    @ObservedObject var address: Address
    
    var body: some View {
        Form {
            TextField("name", text: $address.name)
            
            TextField("age", text: $address.age)
        }
        
    }
}

此代码不起作用:如果我转到 AddressDetail-View,更改 TextField 值然后返回,则更改不会在 List-View 中更新。

妮可

【问题讨论】:

    标签: data-binding swiftui navigationlink


    【解决方案1】:

    问题在于Address 是一个类,因此如果其发布的属性发生更改,addresses 中的引用不会更改,但ContentView 视图将addressbook 视为地址容器。

    这里是可能方法的演示(经过测试并适用于 Xcode 12b / iOS 14,也在 11.4 / iOS 13.4 上)

    List (addressbook.addresses) {address in
        NavigationLink(destination: AddressDetail(address: address)) {
            Text(address.name)
                .onReceive(address.objectWillChange) { _ in
                    self.addressbook.objectWillChange.send()
                }
        }
    }
    

    替代方案:基于Binding(需要更多更改,所以对我而言,不太可取,但值得一提

    struct Address: Identifiable, Hashable {
        let id = UUID()
        var name: String
        var age: String
    
        init(name: String, age: String) {
            self.name = name
            self.age = age
        }
    }
    class AddressBook: ObservableObject {
        @Published var addresses: [Address]
    
        init(addresses: [Address]) {
            self.addresses = addresses
        }
    }
    struct TestData {
        static let addressbook = AddressBook(addresses: [
            Address(name: "Person1", age: "39"),
            Address(name: "Person2", age: "22")
        ])
    }
    
    struct ContentView: View {
        @ObservedObject var addressbook = TestData.addressbook
    
        var body: some View {
            NavigationView {
                List (Array(addressbook.addresses.enumerated()), id: \.element) { i, address in
                    NavigationLink(destination: AddressDetail(address: self.$addressbook.addresses[i])) {
                        Text(address.name)
                    }
                }
                .navigationBarTitle("Addressbook")
            }
    
        }
    }
    
    struct AddressDetail: View {
        @Binding var address: Address
    
        @State private var name: String
        @State private var age: String
    
        init(address: Binding<Address>) {
            _address = address
            _name = State(initialValue: _address.wrappedValue.name)
            _age = State(initialValue: _address.wrappedValue.age)
        }
        var body: some View {
            Form {
                TextField("name", text: $name)
    
                TextField("age", text: $age)
            }
            .onDisappear {
                self.address.name = self.name
                self.address.age = self.age
            }
        }
    }
    

    【讨论】:

    • 谢谢,它有效!但是这个问题没有其他解决方案吗?在我看来,导航视图中列表后面的编辑表单经常被使用。我想将地址参数作为 $address 之类的东西传递,但这似乎在闭包中不起作用。你会如何用@environmentObject 解决这个问题?
    • @Nico, @EnvironmentObject 的行为与@ObservedObject 相同,因此原始问题仍然如第一段所述。另一种方法是使用@Binding - 请参阅更新以了解使用情况。
    猜你喜欢
    • 2021-12-11
    • 1970-01-01
    • 2020-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多