【问题标题】:Binding accepting enums that conform to one protocol in Swift绑定接受符合 Swift 中一种协议的枚举
【发布时间】:2020-03-05 07:53:19
【问题描述】:

我有两个符合一个协议的枚举,一个包含这些枚举数组的可观察对象和一个我想接受这两个枚举的视图。

可观察对象:

class OptionsStore: ObservableObject {
    @Published var topicOptions: [TopicOption]
    @Published var levelOptions: [LevelOption]
}

枚举和协议之一:

enum TopicOption: String, CaseIterable, OptionCompatible {
    case music, food, traffic

    ...
}

protocol OptionCompatible {
    ...
}

意见:

struct MainView: View {
    @EnvironmentObject var optionsStore: OptionsStore

    var body: some View {
        OptionsView(
            options: TopicOption.allCases,                   // no error
            activeOptions: self.$optionsStore.topicOptions   // error
        )
    }
}

struct OptionsView: View {
    let options: [OptionCompatible]
    @Binding var activeOptions: [OptionCompatible]
}

错误是

无法将“Binding”类型的值转换为预期的参数类型“Binding”

我想要的是OptionsView 接受两个枚举。为什么调用静态allCases 会很顺利,但当我传递这些枚举的数组时却不行?我该如何解决这个问题?

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    注意这两行的区别:

    options: TopicOption.allCases,                   // no error
    activeOptions: self.$optionsStore.topicOptions   // error
    

    是第一个不涉及Binding。通常,子类型数组可以分配给超类型数组类型的变量。这不适用于Binding<[Subtype]>Binding<[Supertype]>

    这是因为Binding 不仅需要获取您传入的值。它还需要设置它。回想一下将Binding<String> 传递给TextField 的常见场景。 Binding的值会随着用户输入文字而改变,对吧?

    OptionsView 声明一个Binding<[OptionCompatible]>。这就是说它可能会在数组中添加某种OptionCompatible 类型。但是您将其传递给[TopicOptions]!如果OptionsView想在数组中添加一个LevelOption,例如,它不能!

    您可能会说“但我确信我的OptionsView 只会添加正确类型的对象!”好吧,对编译器说这个的方法是让OptionsView泛型:

    struct OptionsView<OptionType: OptionCompatible>: View {
        let options: [OptionType]
        @Binding var activeOptions: [OptionType]
    
    }
    

    【讨论】:

    • 这非常有用,让我可以清理一些让我很痛苦的令人烦恼的代码。谢谢!
    猜你喜欢
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多