0
0
iOS Swiftmobile~20 mins

Why async/await simplifies concurrent code in iOS Swift - Build It to Prove It

Choose your learning style9 modes available
Build: AsyncAwaitDemo
This screen shows how async/await makes running tasks one after another easier to read and understand compared to old callback style.
Target UI
-------------------------
| Async/Await Demo      |
|-----------------------|
| [Start Tasks]         |
|                       |
| Result:               |
|                       |
|                       |
-------------------------
Add a button labeled 'Start Tasks' that triggers two asynchronous tasks sequentially.
Each task waits 2 seconds and returns a string result.
Display the combined result of both tasks in the Result area after both complete.
Use async/await syntax to run tasks sequentially.
Show a loading indicator while tasks run.
Starter Code
iOS Swift
import SwiftUI

struct AsyncAwaitDemo: View {
    @State private var resultText = ""
    @State private var isLoading = false

    var body: some View {
        VStack(spacing: 20) {
            Text("Async/Await Demo")
                .font(.title)

            Button("Start Tasks") {
                // TODO: Call async function to run tasks
            }
            .padding()
            .disabled(isLoading)

            if isLoading {
                ProgressView()
            }

            Text("Result: \n" + resultText)
                .padding()
                .multilineTextAlignment(.center)

            Spacer()
        }
        .padding()
    }

    // TODO: Add async functions and task runner here
}

struct AsyncAwaitDemo_Previews: PreviewProvider {
    static var previews: some View {
        AsyncAwaitDemo()
    }
}
Task 1
Task 2
Task 3
Task 4
Solution
iOS Swift
import SwiftUI

struct AsyncAwaitDemo: View {
    @State private var resultText = ""
    @State private var isLoading = false

    var body: some View {
        VStack(spacing: 20) {
            Text("Async/Await Demo")
                .font(.title)

            Button("Start Tasks") {
                Task {
                    await runTasksSequentially()
                }
            }
            .padding()
            .disabled(isLoading)

            if isLoading {
                ProgressView()
            }

            Text("Result: \n" + resultText)
                .padding()
                .multilineTextAlignment(.center)

            Spacer()
        }
        .padding()
    }

    func taskOne() async -> String {
        try? await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
        return "Task One Done"
    }

    func taskTwo() async -> String {
        try? await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
        return "Task Two Done"
    }

    func runTasksSequentially() async {
        isLoading = true
        let firstResult = await taskOne()
        let secondResult = await taskTwo()
        resultText = "\(firstResult) and \(secondResult)"
        isLoading = false
    }
}

struct AsyncAwaitDemo_Previews: PreviewProvider {
    static var previews: some View {
        AsyncAwaitDemo()
    }
}

This example uses Swift's async/await to run two tasks one after another. Each task waits 2 seconds and returns a string. The runTasksSequentially function awaits each task in order, making the code easy to read like normal sequential code.

The button triggers the async function using Task { await ... }. While tasks run, a loading spinner shows and the button disables to prevent multiple taps.

This approach is simpler and cleaner than nested callbacks or completion handlers. It reads like normal code but runs asynchronously without blocking the UI.

Final Result
Completed Screen
-------------------------
| Async/Await Demo      |
|-----------------------|
| [Start Tasks]         |
|                       |
| Loading...            |
|                       |
| Result:               |
| Task One Done and     |
| Task Two Done         |
-------------------------
User taps 'Start Tasks' button.
Loading spinner appears and button disables.
After 4 seconds total, result text updates to 'Task One Done and Task Two Done'.
Loading spinner disappears and button re-enables.
Stretch Goal
Add a third async task that runs concurrently with the second task and combine all results.
💡 Hint
Use async let to start tasks concurrently and await their results together.