在下面的代码中,我希望我的 ContentView 在调用“Update”swipeAction 后更新,这反过来又可以更新所选国家/地区的人口值。返回正确的值,但不会触发 ContentView 更新所选国家/地区的人口值。
import SwiftUI
class Country: ObservableObject {
var id = UUID()
@Published var code: String
@Published var population: Int
init(code: String, population: Int) {
self.code = code
self.population = population
}
}
typealias Countries = [Country]
struct ContentView: View {
@State var showPopover = false
@State var selectedCountry: Country = Country(code: "??", population: 0)
@State var newValue: Int = 0
@State var countries: Countries = Countries()
var body: some View {
List (countries, id: \.id) { country in
HStack {Spacer(); Text(country.code); Spacer(); Text("\(country.population)"); Spacer()
}.font(.title)
.swipeActions(content: {
Button { selectedCountry = country; showPopover = true } label: { Text("Update") }
})
}.popover(isPresented: $showPopover) {
PopoverView(country: $selectedCountry)
}.onAppear {
if countries.isEmpty {
countries.append(contentsOf:
[Country(code: "AU", population: 26000000),
Country(code: "US", population: 332000000),
Country(code: "UK", population: 67000000)
])
}
}
}
}
struct PopoverView: View {
@Environment(\.presentationMode) var presentationMode
@Binding var country: Country
@State var value = "???"
var body: some View {
HStack {
Spacer()
Text(country.code)
TextField(country.code, text: $value)
Button {
if let intValue = Int(value) { country.population = intValue }
print("New population: \(country.population)")
presentationMode.wrappedValue.dismiss()
}
label: { Text("DONE")}
Spacer()
}.onAppear {
value = String(country.population)
}
}
}
我已经尝试了许多在线文章中建议的所有内容,但似乎没有什么可以导致 ContentView 更新选定的人口
我已经深入研究了您的问题并找到了解决方案。您的解决方案不起作用,因为您正在编辑 selectedCountry 变量(并且从未真正显示它)而不是集合值本身。首先,我需要像这样重构你的模型:
class CountryContainer: ObservableObject {
@Published var countries = [Country]()
init(countries: [Country] = [Country]()) {
self.countries = countries
}
}
class Country: ObservableObject, Identifiable {
var id = UUID()
@Published var code: String
@Published var population: Int
init(code: String, population: Int) {
self.code = code
self.population = population
}
}
将您的国家/地区存储到 ObservableObject 类中,我还使您的 Country 类可识别,因为它已经有一个 ID,因此在循环它时我们不会遇到任何问题。
然后我编辑了您的 Popover 视图以接受一个函数:
struct PopoverView: View {
@Environment(\.presentationMode) var presentationMode
@Binding var country: Country
@State var value = "???"
var onCountryChanged: () -> Void
var body: some View {
HStack {
Spacer()
Text(country.code)
TextField(country.code, text: $value)
Button {
if let intValue = Int(value) { country.population = intValue }
print("New population: \(country.population)")
presentationMode.wrappedValue.dismiss()
onCountryChanged()
}
label: { Text("DONE")}
Spacer()
}.onAppear {
value = String(country.population)
}
}
}
编辑操作完成后我就调用了该函数。 然后,我使用您的 selectedCountry 来编辑存储在 CountryContainer StateObject 中的实际集合值,如下所示:
@State var showPopover = false
@State var selectedCountry: Country = Country(code: "??", population: 0)
@State var newValue: Int = 0
@StateObject var countryContainer = CountryContainer()
var body: some View {
List (countryContainer.countries) { country in
HStack {
Spacer()
Text(country.code)
Spacer()
Text("\(country.population)");
Spacer()
}
.font(.title)
.swipeActions(content: {
Button {
selectedCountry = country
showPopover = true
} label: {
Text("Update")
}
})
}.popover(isPresented: $showPopover) {
PopoverView(country: $selectedCountry) {
let countryToEditIndex = countryContainer.countries.firstIndex(where: { $0.id == selectedCountry.id })
countryContainer.countries[countryToEditIndex!] = selectedCountry
}
}.onAppear {
if countryContainer.countries.isEmpty {
countryContainer.countries.append(contentsOf:
[Country(code: "AU", population: 26000000),
Country(code: "US", population: 332000000),
Country(code: "UK", population: 67000000)
])
}
}
}
这个解决方案可能不是最好的,您可以找到改进它的方法,但我只是想为您指出正确的方向。 我希望我能帮助你,我的解释很清楚。让我知道!