0

I'm trying to implement a simple toggle switch but I'm having trouble saving the new toggle/switch status as when I change views and go back into the setting, it's defaulted back to the off switch. Can you tell me what I'm doing wrong?

struct StudyMode: View {
      @State private var overdueFirst = UserDefaults.standard.bool(forKey: "Overdue First")
      @EnvironmentObject var settings: UserSettings

      var body: some View {
        VStack {
          HStack {
            Toggle(isOn: $overdueFirst) {
              Text("Overdue cards first")
            }
            .onTapGesture {
              var newSwitch = false

              if self.overdueFirst == false {
                newSwitch = true
              }

              UserDefaults.standard.set(newSwitch, forKey: "Overdue First")
            }
          }

          Spacer()
          Text("By enabling this option, the cards will be ordered such that you will revise all overdue cards before you start learning new words.")
            .font(.system(size: 12))
        }
      }
    }
alamodey
  • 14,320
  • 24
  • 86
  • 112
  • try loading the value from user defaults in `onAppear()` and debug to see whats happening. Aso `onTapGuesture` can be reduced to `self.overdueFirst.toggle()` – Umair M Mar 03 '20 at 12:20

1 Answers1

1

Your .onTapGesture over Toggle is not called, because latter does not allow it (handling tap by itself, and even .simultaneousGesture will not help)

Here is possible approach to achieve the goal (tested with Xcode 11.2 / iOS 13.2)

...
// define proxy binding, wrapping direct work with UserDefaults
private let overdueFirst = Binding<Bool>(
    get: { UserDefaults.standard.bool(forKey: "Overdue First") },
    set: { UserDefaults.standard.set($0, forKey: "Overdue First") })

var body: some View {
  VStack {
    HStack {
      Toggle(isOn: overdueFirst) { // use proxy binding directly
        Text("Overdue cards first")
      }
    }
    ...

However I would recommend to bind this Toggle directly with your UserSettings corresponding property and handle sync with UserDefaults there (eg. on didSet).

Asperi
  • 228,894
  • 20
  • 464
  • 690