为什么 SwiftUi 视图在从 swipeActions 调用的弹出窗口中更改值后不更新?

问题描述 投票:0回答:1

在下面的代码中,我希望我的 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 更新选定的人口

swiftui swipe popover
1个回答
0
投票

我已经深入研究了您的问题并找到了解决方案。您的解决方案不起作用,因为您正在编辑 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)
                                ])
        }
    }
}

这个解决方案可能不是最好的,您可以找到改进它的方法,但我只是想为您指出正确的方向。 我希望我能帮助你,我的解释很清楚。让我知道!

© www.soinside.com 2019 - 2024. All rights reserved.