1

In the following code, I'm trying to save the color theme in UserDefaults using the SwiftUI @AppStorage wrapper. What I would like to do is be able to call a method to save the rawValue from the ColorTheme enum when a segment is tapped, for instance, if the System segment is tapped I would like to save nil as a String in UserDefaults, basically assign the rawValue to the appTheme wrapper inside the function, something like...

func assignTheme(segment){
    appTheme = segment.rawValue
}

How can I call a function when a segment is tapped and be able to recognize what segment was tapped to be able to assign the appropriate value to the appTheme wrapper?

import SwiftUI

enum ColorTheme: String {
    case system = "nil"
    case light = "light"
    case dark = "dark"
}

struct SegmentedView: View {
    
    @AppStorage("appTheme") private var appTheme = ColorTheme.system.rawValue
    
    var body: some View {
        VStack{
            List{
                Section(header: Text("Theme")){
                    Picker("Mode", selection: $appTheme){
                        Text("System").tag(ColorTheme.system.rawValue)
                        Text("Light").tag(ColorTheme.light.rawValue)
                        Text("Dark").tag(ColorTheme.dark.rawValue)
                    }.pickerStyle(SegmentedPickerStyle())
                        .padding()
                }
            }
        }
    }
}

struct SegmentedView_Previews: PreviewProvider {
    static var previews: some View {
        SegmentedView()
    }
}
fs_tigre
  • 10,650
  • 13
  • 73
  • 146

2 Answers2

2

Here is what I ended up doing.

Picker("Mode", selection: $appTheme){
    Text("System").tag(ColorTheme.system.rawValue)
    Text("Light").tag(ColorTheme.light.rawValue)
    Text("Dark").tag(ColorTheme.dark.rawValue)
}
.pickerStyle(SegmentedPickerStyle())
.padding()
.onChange(of: appTheme) {tag in
    appTheme = tag
    // call someFunction()
}
fs_tigre
  • 10,650
  • 13
  • 73
  • 146
1

You can try this:

    var body: some View {
        VStack{
            List{
                Section(header: Text("Theme")){
                    Picker("Mode", selection: $appTheme.onChange(doSomething)){
                        Text("System").tag(ColorTheme.system.rawValue)
                        Text("Light").tag(ColorTheme.light.rawValue)
                        Text("Dark").tag(ColorTheme.dark.rawValue)
                    }
                    .pickerStyle(SegmentedPickerStyle())
                    .padding()

                }

            }
        }
    }

    func doSomething(_ some: String) {
        print(appTheme)
    }

onChange is here: SwiftUI Picker onChange or equivalent?

Maetschl
  • 1,330
  • 14
  • 23
  • 2
    I kept getting error `Cannot call value of non-function type 'Binding' Generic parameter 'SelectionValue' could not be inferred`. I actually used the `.onChange` modifier directly in the `Picker`. Thanks – fs_tigre Jan 24 '22 at 19:23