title: UserDefaults Binding with Toggle in SwiftUI
body: <p>I'm trying to figure out the best way to build <strong>a simple settings screen bound to UserDefaults</strong>.</p>
  
  <p>Basically, I have a Toggle and I want:</p>
  
  <ul>
  <li>the value a UserDefault to be saved any time this Toggle is changed (the UserDefault should be the source of truth)</li>
  <li>the Toggle to always show the value of the UserDefault</li>
  </ul>
  
  <p><a href="https://i.stack.imgur.com/uBDzp.png" rel="noreferrer"><img src="https://i.stack.imgur.com/uBDzp.png" alt="Settings screen with Toggle"></a></p>
  
  <p>I have watched many of the SwiftUI WWDC sessions, but I'm still not sure exactly how I should set everything up with the different tools that are available within Combine and SwiftUI. My current thinking is that I should be using a BindableObject so I can use hat to encapsulate a number of different settings.</p>
  
  <p>I think I am close, because it almost works as expected, but the behavior is inconsistent.</p>
  
  <p>When I build and run this on a device, I open it and turn on the Toggle, then if I scroll the view up and down a little the switch toggles back off (as if it's not actually saving the value in UserDefaults).</p>
  
  <p>However, if I turn on the switch, leave the app, and then come back later it is still on, like it remembered the setting.</p>
  
  <p>Any suggestions? I'm posting this in hopes it will help other people who are new to SwiftUI and Combine, as I couldn't find any similar questions around this topic.</p>
  
  <pre><code>import SwiftUI
  import Combine
  
  struct ContentView : View {
  
      @ObjectBinding var settingsStore = SettingsStore()
  
      var body: some View {
          NavigationView {
              Form {
                  Toggle(isOn: $settingsStore.settingActivated) {
                      Text("Setting Activated")
                  }
              }
          }.navigationBarTitle(Text("Settings"))
      }
  }
  
  class SettingsStore: BindableObject {
  
      var didChange = NotificationCenter.default.publisher(for: .settingsUpdated).receive(on: RunLoop.main)
  
      var settingActivated: Bool {
          get {
              UserDefaults.settingActivated
          }
          set {
              UserDefaults.settingActivated = newValue
          }
      }
  }
  
  extension UserDefaults {
  
      private static var defaults: UserDefaults? {
          return UserDefaults.standard
      }
  
      private struct Keys {
          static let settingActivated = "SettingActivated"
      }
  
      static var settingActivated: Bool {
          get {
              return defaults?.value(forKey: Keys.settingActivated) as? Bool ?? false
          }
          set {
              defaults?.setValue(newValue, forKey: Keys.settingActivated)
          }
      }
  }
  
  extension Notification.Name {
      public static let settingsUpdated = Notification.Name("SettingsUpdated")
  }
  </code></pre>