title: Create a computed @State variable in SwiftUI
body: <p>Imagine I'm designing a SwiftUI screen that asks for the user to enter a Username. The screen will do some checking to ensure the username is valid. If the username is invalid, it'll show an error message. If the user taps "Dismiss", it'll hide the error message.</p>
  
  <p>In the end I may end up with something like this:</p>
  
  <blockquote>
    <p><a href="https://i.stack.imgur.com/Y752sl.png" rel="noreferrer"><img src="https://i.stack.imgur.com/Y752sl.png" alt="enter image description here"></a></p>
  </blockquote>
  
  <pre><code>enum UsernameLookupResult: Equatable {
      case success
      case error(message: String, dismissed: Bool)
  
      var isSuccess: Bool { return self == .success }
      var isVisibleError: Bool {
          if case .error(message: _, dismissed: false) = self {
              return true
          } else {
              return false
          }
      }
      var message: String {
          switch self {
          case .success:
              return "That username is available."
          case .error(message: let message, dismissed: _):
              return message
          }
      }
  }
  
  enum NetworkManager {
      static func checkAvailability(username: String) -&gt; UsernameLookupResult {
          if username.count &lt; 5 {
              return .error(message: "Username must be at least 5 characters long.", dismissed: false)
          }
  
          if username.contains(" ") {
              return .error(message: "Username must not contain a space.", dismissed: false)
          }
  
          return .success
      }
  }
  
  class Model: ObservableObject {
      @Published var username = "" {
          didSet {
              usernameResult = NetworkManager.checkAvailability(username: username)
          }
      }
      @Published var usernameResult: UsernameLookupResult = .error(message: "Enter a username.", dismissed: false)
  
      func dismissUsernameResultError() {
          switch usernameResult {
          case .success:
              break
          case .error(message: let message, dismissed: _):
              usernameResult = .error(message: message, dismissed: true)
          }
      }
  }
  
  struct ContentView: View {
      @ObservedObject var model: Model
  
      var body: some View {
          VStack {
              Form {
                  TextField("Username", text: $model.username)
                  Button("Submit", action: {}).disabled(!model.usernameResult.isSuccess)
              }
              Spacer()
              if model.usernameResult.isSuccess || model.usernameResult.isVisibleError {
                  HStack(alignment: .top) {
                      Image(systemName: model.usernameResult.isSuccess ? "checkmark.circle" : "xmark.circle")
                          .foregroundColor(model.usernameResult.isSuccess ? Color.green : Color.red)
                          .padding(.top, 5)
                      Text(model.usernameResult.message)
                      Spacer()
                      if model.usernameResult.isSuccess {
                          EmptyView()
                      } else {
                          Button("Dismiss", action: { self.model.dismissUsernameResultError() })
                      }
                  }.padding()
              } else {
                  EmptyView()
              }
          }
      }
  }
  </code></pre>
  
  <p>As long as my "dismiss" action is a <code>Button</code>, it's easy to achieve the dismiss behavior:</p>
  
  <pre><code>Button("Dismiss", action: { self.model.dismissUsernameResultError() })
  </code></pre>
  
  <p>This will easily show error messages and dismiss them correctly.</p>
  
  <p>Now imagine I want to use a different component instead of Button to call the dismiss method. Furthermore, imagine the component I use only takes in a <code>Binding</code> (e.g. a <code>Toggle</code>). (Note: I realize this is not an ideal component to use, but this is for illustrative purposes in this simplified demo app.) I may attempt to create a <a href="https://stackoverflow.com/questions/59339650/what-do-you-call-a-variable-that-has-a-getter-and-setter-defined-with-no-backin/59339818#59339818">computed property</a> to abstract this behavior and end up with:</p>
  
  <pre><code>@State private var bindableIsVisibleError: Bool {
      get { return self.model.usernameResult.isVisibleError }
      set { if !newValue { self.model.dismissUsernameResultError() } }
  }
  
  // ...
  
  
  // replace Dismiss Button with:
  Toggle(isOn: $bindableIsVisibleError, label: { EmptyView() })
  </code></pre>
  
  <p>... however, this is not valid syntax and produces the following error on the <code>@State</code> line:</p>
  
  <blockquote>
    <p>Property wrapper cannot be applied to a computed property</p>
  </blockquote>
  
  <p>How can I create a bindable computed property? I.e. a <code>Binding</code> with a custom getter and setter.</p>
  
  <hr>
  
  <p>Although not ideal as it would (A) only provide a setter, and (B) adds state duplication (which goes against SwiftUI's single source of truth principal), I thought I would be able to solve this with a normal state variable:</p>
  
  <pre><code>@State private var bindableIsVisibleError: Bool = true {
      didSet { self.model.dismissUsernameResultError() }
  }
  </code></pre>
  
  <p>This does not work, though as <code>didSet</code> is never called.</p>