Thuta Learning
AdvancedMobile Developmentintermediate

Swift Concurrency (Task, async/await Deep Dive)

Relax. We'll talk through this in plain words — no textbook voice.

What you'll walk away with

  • Understand Swift Concurrency (Task, async/await Deep Dive) with nothing to be intimidated by
  • Get comfortable running Xcode/SwiftUI code yourself
  • Be able to apply this concept in a real project right away

Let's think about it this way for a second

`Task { }` is a 'container' for starting asynchronous work — inside a SwiftUI View, you'll typically use the `.task { }` modifier (which runs automatically when the View appears, essentially a shortcut combining `.onAppear` + `Task`). Annotating a class/function with `@MainActor` tells the compiler 'only run this code on the UI thread' — since `@Published` property updates (from the ViewModel lesson) must happen on the main thread, ViewModel classes are usually annotated with `@MainActor`.

Let's connect this to a real-world scenario

Instead of writing `.onAppear { Task { ... } }` in `WeatherScreen`, it's cleaner to write `.task { weather = try? await fetchWeather(city: "Yangon") }` — the `.task` modifier automatically cancels when the View disappears (with `.onAppear` + a manual `Task`, you'd have to write the cancel logic yourself).

Let's look at it together

swift
@MainActor
class WeatherViewModel: ObservableObject {
    @Published var weather: WeatherResponse?

    func loadWeather(city: String) async {
        weather = try? await fetchWeather(city: city)
    }
}

struct WeatherScreen: View {
    @StateObject private var viewModel = WeatherViewModel()

    var body: some View {
        Text(viewModel.weather?.city ?? "Loading...")
            .task {
                await viewModel.loadWeather(city: "Yangon")
            }
    }
}
You should see
As soon as you land on the screen, you'll see it automatically update from 'Loading...' to the weather city name.

5-minute try-it

Write `WeatherViewModel`/`WeatherScreen` yourself using the `.task { }` modifier — try navigating away from the screen right away and observe `.task`'s auto-cancel behavior.

A quick heads-up

Overusing `try?` inside a `Task { }` without catching errors (silent failure) means neither the user nor the developer knows an error even happened, which makes debugging much harder.

Easy traps

  • Directly updating a `@Published` property from a background thread without `@MainActor` — this carries undefined behavior/crash risk
  • Forgetting to manually write cancel logic when using `.onAppear` + a manual `Task { }` — using the `.task { }` modifier instead lets the framework handle this concern for you

Now try it yourself

Write `WeatherViewModel`/`WeatherScreen` yourself using the `.task { }` modifier — try navigating away from the screen right away and observe `.task`'s auto-cancel behavior.

You'll know it worked when: As soon as you land on the screen, you'll see it automatically update from 'Loading...' to the weather city name.

Swift Concurrency (Task, async/await Deep Dive) | Thuta Learning