title: Swift 4: getter and setter directly in a struct or class
body: <p>I am trying to come up with a way to access UserDefaults using properties. However, I am stuck because I can't figure out how to make the properties dynamic, so to speak.</p>
  
  <p>This is the generic idea, that API that I <em>want</em>:</p>
  
  <pre><code>class AppUserDefaults {
    var username = DefaultsKey&lt;String&gt;("username", defaultValue: "Unknown")
    var age = DefaultsKey&lt;Int?&gt;("age", defaultValue: nil)
  }
  
  let props = AppUserDefaults()
  props.username = "bla"
  print("username: \(props.username)")
  </code></pre>
  
  <p>But that (of course) doesn't work, since the type is <code>DefaultsKey&lt;String&gt;</code>, not <code>String</code>. So I have to add a value property to the <code>DefaultsKey</code> implementation just to add the getter and the setter, like this:</p>
  
  <pre><code>struct DefaultsKey&lt;ValueType&gt; {
    private let key: String
    private let defaultValue: ValueType
  
    public init(_ key: String, defaultValue: ValueType) {
      self.key = key
      self.defaultValue = defaultValue
    }
  
    var value: ValueType {
      get {
        let value = UserDefaults.standard.object(forKey: key)
        return value as? ValueType ?? defaultValue
      }
      set {
        UserDefaults.standard.setValue(newValue, forKey: key)
        UserDefaults.standard.synchronize()
      }
    }
  }
  </code></pre>
  
  <p>and then use it like this:</p>
  
  <pre><code>let props = AppUserDefaults()
  props.username.value = "bla"
  print("username: \(props.username.value)")
  </code></pre>
  
  <p>But I find that rather ugly. I also tried a subscript method, but then you're still required to add <code>[]</code> instead of <code>.value</code>:</p>
  
  <pre><code>struct DefaultsKey&lt;ValueType&gt; {
    ...
    subscript() -&gt; ValueType {
      get {
        let value = UserDefaults.standard.object(forKey: key)
        return value as? ValueType ?? defaultValue
      }
      set {
        UserDefaults.standard.setValue(newValue, forKey: key)
        UserDefaults.standard.synchronize()
      }
    }
  }
  
  let props = AppUserDefaults()
  props.username[] = "bla"
  print("username: \(props.username[])")
  </code></pre>
  
  <p>Basically what I want is that I can define the getter and the setter directly on <code>DefaultsKey</code> instead of having to go through that <code>value</code> property. Is this simply not possible with Swift? Is there another way to get the behaviour that I want, where properties defined on <code>AppUserDefaults</code> are "dynamic" and go through a getter and setter, without having to define it on the property declaration inside of <code>AppUserDefaults</code>?</p>
  
  <p>I hope I am using the correct terms here and made the question clear for everyone.</p>