【问题标题】:SwiftUI picker driven by an enum: value not updated由枚举驱动的 SwiftUI 选择器:值未更新
【发布时间】:2020-10-09 08:15:55
【问题描述】:

根据 Apple 关于Picker in SwiftUI using an Enum 的文档,如果枚举除了CaseIterable 之外还符合Identifiable 协议,则遍历所有案例的选择器应该本地更新绑定变量。

我测试了它,它没有按预期工作。

enum Flavor: String, CaseIterable, Identifiable {
    case chocolate
    case vanilla
    case strawberry

    var id: String { self.rawValue }
}

struct EnumView: View {
    @State private var selectedFlavor = Flavor.chocolate
    var body: some View {
        VStack {
            Picker("Flavor", selection: $selectedFlavor) {
                ForEach(Flavor.allCases) { flavor in
                    Text(flavor.rawValue.capitalized)//.tag(flavor)
                }
            }
        
            Text("Selected flavor: \(selectedFlavor.rawValue)")
        }
    }
}

但是,如果我为每个视图传递一个tag,它就会起作用。

这里发生了什么?苹果文档有错吗? selectedFlavor 变量需要 Flavor 类型的值,但选择器中使用的 id 实际上是 String

谢谢。

【问题讨论】:

    标签: swiftui swiftui-picker


    【解决方案1】:

    要使Picker 正常工作,需要识别其元素。

    请注意,selectedFlavor 变量的类型为 Flavor。这意味着 Picker 中的选项应该被标识为 Flavors(而不是 Strings)。

    但是,在您的代码中,您的 idString 类型:

    var id: String { self.rawValue }
    

    您可以:

    • 提供tagFlavor 类型):
    Text(flavor.rawValue.capitalized)
        .tag(flavor)
    
    • 通过提供 Flavor 类型的自定义 id 使 FlavorIdentifiable 一致:
    var id: Flavor { self }
    
    • ForEach 中明确指定id 参数(Flavor 类型):
    ForEach(Flavor.allCases, id: \.self) { ... }
    
    • selectedFlavor 更改为字符串:
    @State private var selectedFlavor = Flavor.chocolate.rawValue
    

    【讨论】:

    • 但是当元素符合 Identifiable 时,ForEach 应该使用每个选项的 id 自动为选择器中的选择视图分配一个标签。我不明白为什么选择器不会自动将用作标签的字符串 id 转换为使用此 id 的 rawValue 作为标签的枚举。
    • @alpennec 我添加了更详细的解释。我希望现在更清楚了。
    • 感谢您的解释。列出所有可能的选项是件好事。如果我理解得很好,当传递给 ForEach 循环的项目符合 Identifiable 时(即我们不需要告诉要使用的 id),为 ForEach 循环中的每个视图生成的标签是 id? So if we have an id of type String for an Enum, then the tag for the view is a String, and when the picker selects an item, it selects a String whereas the expected value for the selection is an Enum.对吗?
    • @alpennec 是的,没错。基本上问题是关于使用字符串标记值并期望将 Flavor 作为所选项目。
    【解决方案2】:

    这是对@pawello2222 已经很棒的答案的补充。

    只是为了澄清使用以下代码使枚举符合 Identifiable 的解决方案可以正确标记 UI 选择器,而无需在选择器代码中明确声明它:

    var id: Flavor { self }
    

    官方Apple documentation for the swiftUI picker 说使用var id: String { self.rawValue } 对枚举进行标识,但使用示例代码的其余部分无法按预期工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多