title: Work with Binding inside an external function in SwiftUI
body: <p>I'm currently learning SwiftUI and want to develop my own app. I have designed a <code>LoginView</code> and a <code>LoginHandler</code> that should take care of all the logic behind a login. When the user enters the wrong username/password, an Alert should appear on the screen. I solved this with the state variable <code>loginError</code>. But now comes the tricky part, as i want to pass a binding of this variable to my login function in the <code>LoginHandler</code>. Take a look at the following code:</p>
  <pre class="lang-swift prettyprint-override"><code>
  import SwiftUI
  
  struct LoginView: View
  {
      @EnvironmentObject var loginHandler: LoginHandler
      
      @State private var username: String = &quot;&quot;
      @State private var password: String = &quot;&quot;
      @State private var loginError: Bool = false
      
      ...
      
      private func login()
      {
          loginHandler.login(username: username, password: password, error: $loginError)
      }
  }
  </code></pre>
  <p>I am now trying to change the value of error inside my login function:</p>
  <pre class="lang-swift prettyprint-override"><code>import Foundation
  import SwiftUI
  
  class LoginHandler: ObservableObject
  {
      public func login(username: String, password: String, error: Binding&lt;Bool&gt;)
      {
          error = true
      }
  }
  </code></pre>
  <p>But I'm getting the error</p>
  <blockquote>
  <p>Cannot assign to value: 'error' is a 'let' constant</p>
  </blockquote>
  <p>which makes sense I think because you can't edit the parameters in swift. I have also tried <code>_error = true</code> because I once saw the underscore in combination with a binding, but this doesn't worked either.</p>
  <p>But then I came up with a working solution: <code>error.wrappedValue = true</code>. My only problem with that is the following statement from Apples Developer Documentation:</p>
  <blockquote>
  <p>This property provides primary access to the value’s data. However, you don’t access wrappedValue directly. Instead, you use the property variable created with the @Binding attribute.</p>
  </blockquote>
  <p>Although I'm super happy that it works, I wonder if there is any better way to solve this situation?</p>
  <h3>Update 20.3.21: New edge case</h3>
  <p>In the comment section I mentioned a case where you don't know how many times your function will be used. I will now provide a little code example:</p>
  <p>Imagine a list of downloadable files (<code>DownloadView</code>) that you will get from your backend:</p>
  <pre class="lang-swift prettyprint-override"><code>import SwiftUI
  
  struct DownloadView: View
  {
      @EnvironmentObject var downloadHandler: DownloadHandler
      
      var body: some View
      {
          VStack
          {
              ForEach(downloadHandler.getAllDownloadableFiles())
              {
                  file in DownloadItemView(file: file)
              }
          }
      }
  }
  </code></pre>
  <p>Every downloadable file has a name, a small description and its own download button:</p>
  <pre class="lang-swift prettyprint-override"><code>import SwiftUI
  
  struct DownloadItemView: View
  {
      @EnvironmentObject var downloadHandler: DownloadHandler
      
      @State private var downloadProgress: Double = -1
      
      var file: File
      
      var body: some View
      {
          HStack
          {
              VStack
              {
                  Text(file.name)
                  Text(file.description)
              }
              
              Spacer()
              
              if downloadProgress &lt; 0
              {
                  // User can start Download
                  Button(action: {
                      downloadFile()
                  })
                  {
                      Text(&quot;Download&quot;)
                  }
              }
              else
              {
                  // User sees download progress
                  ProgressView(value: $downloadProgress)
              }
          }
      }
      
      func downloadFile()
      {
          downloadHandler.downloadFile(file: file, progress: $downloadProgress)
      }
  }
  </code></pre>
  <p>And now finally the 'DownloadHandler':</p>
  <pre class="lang-swift prettyprint-override"><code>import Foundation
  import SwiftUI
  
  class DownloadHandler: ObservableObject
  {
      public func downloadFile(file: File, progress: Binding&lt;Double&gt;)
      {
          // Example for changing the value
          progress = 0.5
      }
  }
  </code></pre>