title: How can I avoid that my Swift async method runs on the main thread in SwiftUI?
body: <p>I watched all the videos on async/await (and actors), but I am still confused a bit.</p>
  <p>So assume I have an async method: <code>func postMessage(_ message: String) async throws</code> and I have a simple SwiftUI view.</p>
  <pre class="lang-swift prettyprint-override"><code>@MainActor 
  struct ContentView: View {
      @StateObject private var api = API()
      
      var body: some View {
          Button(&quot;Post Message&quot;) {
              Task {
                  do {
                      try await api.postMessage(&quot;First post!&quot;)
                  } catch {
                      print(error)
                  }
              }
          }
      }
  }
  </code></pre>
  <p>Here I explicitly tell SwiftUI to use the <code>@MainActor</code> although I know it would have inferred from <code>@StateObject</code>.</p>
  <p>To my understanding, since we use the <code>@MainActor</code> the work is done on the main thread. Meaning the work on Task would also be done on the main thread. Which is not what I want as the uploading process might take some while. In this case I could use <code>Task.detached</code> to use a different thread. Which would solve it. If my understanding is correct.</p>
  <p>Now to make it a little more complicated. What if... postMessage would return a post identifier as an integer and I like to present that in the view?</p>
  <pre class="lang-swift prettyprint-override"><code>struct ContentView: View {
      @StateObject private var api = API()
      @State private var identifier: Int = 0
      
      var body: some View {
          Text(&quot;Post Identifier: \(String(describing: identifier))&quot;)
          Button(&quot;Post Message&quot;) {
              Task {
                  do {
                      identifier = try await api.postMessage(&quot;First post!&quot;)
                  } catch {
                      identifier = 0
                      print(error)
                  }
              }
          }
      }
  }
  </code></pre>
  <p>This would work as (again to my understanding) Task is run on the main thread. If I would change it now to <code>Task.detached</code> we will get an error <code>&quot;Property 'identifier' isolated to global actor 'MainActor' can not be mutated from a non-isolated context&quot;</code>.</p>
  <p>Which makes sense, but how can we return the value to the main actor so the view can be updated?</p>
  <p>Perhaps my assumptions are wrong. Let's look at my API class.</p>
  <pre class="lang-swift prettyprint-override"><code>actor API {
      func postMessage(_ message: String) async throws -&gt; Int {
          // Some complex internet code
          return 0
      }
  }
  </code></pre>
  <p>Since the API runs in its own actor. Would the internet work also run on a different thread?</p>