由枚举驱动的 SwiftUI 选择器:值未更新

Posted

技术标签:

【中文标题】由枚举驱动的 SwiftUI 选择器:值未更新【英文标题】:SwiftUI picker driven by an enum: value not updated 【发布时间】: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

谢谢。

【问题讨论】:

【参考方案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 对枚举进行标识,但使用示例代码的其余部分无法按预期工作。

【讨论】:

以上是关于由枚举驱动的 SwiftUI 选择器:值未更新的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 选择器

SwiftUI - 使用带有枚举的选择器和提供的值并返回正确的 tag()

SwiftUI:更改数据源时选择器无法正确更新

SwiftUI 选择器在 ObservedObject 公共变量更新期间滚动时跳转

导航回视图时更新 SwiftUI 选择器最小值和最大值

使用 SwiftUI 选择器,我的 MacBook 加热到 50 度