在ObservedObject更新时更新选择器

时间:2019-10-10 11:59:41

标签: swift picker

我正在尝试如下向Picker动态添加新行:

class ViewModel: ObservableObject {    
    @Published private (set) var drinks = ["Tea", "Coffee", "Wine"]

    func addDrink(_ drink: String) {
        drinks.append(drink)
    }
}

struct PickerTest: View {

    @State private var selectedDrink = "Tea"
    @State private var customDrink = ""
    @ObservedObject private var viewModel = ViewModel()

    var body: some View {
        VStack {
            HStack {
                TextField("Enter a drink", text: $customDrink)
                Spacer()
                Button("Add") {
                    self.viewModel.addDrink(self.customDrink)
                }
            }
            Picker("Drinks", selection: $selectedDrink) {  // Removing the wrapping Picker works
                ForEach(viewModel.drinks, id: \.self) { drink in
                    Text(drink)
                }
            }
        }.padding().labelsHidden()
    }
}

这不起作用。如果我除去包裹Picker的{​​{1}},则ForEach将按预期更新。

是否可以动态更新ForEach

1 个答案:

答案 0 :(得分:2)

似乎是Picker的错误-我希望Apple在以后的SwiftUI版本中对其进行修复。

我发现丑陋(我真的不喜欢)解决此问题的方法:

class ViewModel: ObservableObject {
    @Published var selectedDrink = "Tea"
    @Published var drinks = ["Tea", "Coffee", "Wine"]
    @Published var drinksChanged = true

    func addDrink(_ drink: String) {
        drinks.append(drink)
        drinksChanged.toggle()
    }
}

struct DrinksPicker: View {
    @ObservedObject var viewModel: ViewModel

    var body: some View {
        Picker("Drinks", selection: $viewModel.selectedDrink) {
            ForEach(viewModel.drinks, id: \.self) { drink in
                Text(drink)
            }
        }
    }
}

struct PickerTest: View {
    @State private var customDrink = ""
    @ObservedObject private var viewModel = ViewModel()

    var body: some View {
        VStack {
            HStack {
                TextField("Enter a drink", text: $customDrink)
                Spacer()
                Button("Add") {
                    self.viewModel.addDrink(self.customDrink)
                    self.customDrink = ""
                }
            }
            if viewModel.drinksChanged {
                DrinksPicker(viewModel: viewModel)
            } else {
                DrinksPicker(viewModel: viewModel)
            }
        }.padding().labelsHidden()
    }
}

您也可以将此if-else隐藏在另一个容器中:

struct DrinksPickerContainer: View {
    @ObservedObject var viewModel: ViewModel

    var body: some View {
        Group {
            if viewModel.drinksChanged {
                DrinksPicker(viewModel: viewModel)
            } else {
                DrinksPicker(viewModel: viewModel)
            }
        }
    }
}

,然后仅在DrinksPickerContainer(viewModel: viewModel)中使用PickerTest