SwiftUI更新父级NavigationView的数据 [英] SwiftUI update data for parent NavigationView

查看:73
本文介绍了SwiftUI更新父级NavigationView的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何更新存在于NavigationView详细信息中的TextField中的数据?我希望在父视图的列表中更新数据.这是我的代码:

how can I update data in TextField that lives in the detail of a NavigationView? I want the data to be updated in the List of the parent View. Here is my code:

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中更新.

This code doesn't work: If I go to the AddressDetail-View, change the TextField values and then go back, the changes don't update in the List-View.

Nico

推荐答案

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

The problem is that Address is a class, so if its published properties changed the reference in addresses is not changed, but ContentView view observes addressbook as a container of addresses.

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

Here is demo of possible approach (tested & works with Xcode 12b / iOS 14, also on 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 (需要进行更多更改,因此,对我而言,较不受欢迎,但值得一提

Alternate: based on Binding (requires much more changes, so, as for me, less preferable, but worth mention

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
        }
    }
}

这篇关于SwiftUI更新父级NavigationView的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆