Search code examples
swiftswiftuipicker

Change a @Published var via Picker


I would like to change a @Published var through the Picker but I found that it fails to compile.

I have a Language struct:

enum Language: Int, CaseIterable, Identifiable, Hashable {
case en
case zh_hant

var description: String {
    switch self {
    case.en:
        return "English"
    case.zh_hant:
        return "繁體中文"
    }
}

var id: Int {
    self.rawValue
}

}

And inside my DataModel, I have published the variable selectedLanguage

final class ModelData: ObservableObject {
    @Published var currentLanguage: Language = Language.zh_hant         
}

I tried to use a picker for the user to change the language:

@EnvironmentObject var modelData: ModelData

In the body of the view:

Picker("Selected Language", selection: modelData.currentLanguage) {
                ForEach(Language.allCases, id: \.rawValue) { language in
                    Text(language.description).tag(language)
                }
            }.pickerStyle(SegmentedPickerStyle()).padding(.horizontal)

It says "Cannot convert value of type 'Language' to expected argument type 'Binding'"

How can I modify the currentLanguage in the modelData directly with the picker?


Solution

  • You were very close. You need to use the $ when making a binding to a @Published property like that:

    Picker("Selected Language", selection: $modelData.currentLanguage) {
                ForEach(Language.allCases, id: \.id) { language in
                    Text(language.description).tag(language)
                }
            }.pickerStyle(SegmentedPickerStyle()).padding(.horizontal)
    
    

    I also changed the id: to \.id rather than \.rawValue which is somewhat meaningless since they resolve to the same thing, but makes a little more sense semantically.