SwiftUI 更新父 NavigationView 的数据
SwiftUI update data for parent NavigationView
如何更新位于 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 中更新。
妮可
问题是 Address
是一个 class,因此如果其发布的属性发生更改,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
}
}
}
如何更新位于 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 中更新。
妮可
问题是 Address
是一个 class,因此如果其发布的属性发生更改,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
}
}
}