0
0
iOS Swiftmobile~20 mins

MainActor for UI updates in iOS Swift - Mini App: Build & Ship

Choose your learning style9 modes available
Build: MainActor UI Update Demo
This screen shows a label and a button. When the button is tapped, it simulates a background task that updates the label text safely on the main thread using @MainActor.
Target UI
-------------------------
| MainActor UI Update Demo |
|-----------------------|
|                       |
|  Label: Waiting...     |
|                       |
|  [ Update Label ]      |
|                       |
-------------------------
Display a label with initial text 'Waiting...'
Add a button labeled 'Update Label'
When button is tapped, simulate a 2-second background task
After task completes, update label text to 'Updated on MainActor!' safely on main thread using @MainActor
Starter Code
iOS Swift
import SwiftUI

struct MainActorDemoView: View {
    @State private var labelText = "Waiting..."

    var body: some View {
        VStack(spacing: 20) {
            Text(labelText)
                .font(.title)
            Button("Update Label") {
                // TODO: Call function to update label
            }
        }
        .padding()
    }

    // TODO: Add function to simulate background task and update label
}

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

struct MainActorDemoView: View {
    @State private var labelText = "Waiting..."

    var body: some View {
        VStack(spacing: 20) {
            Text(labelText)
                .font(.title)
            Button("Update Label") {
                updateLabel()
            }
        }
        .padding()
    }

    func updateLabel() {
        Task {
            try? await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
            await MainActor.run {
                labelText = "Updated on MainActor!"
            }
        }
    }
}

struct MainActorDemoView_Previews: PreviewProvider {
    static var previews: some View {
        MainActorDemoView()
    }
}

We use Task to run an asynchronous background task that simulates a 2-second delay using Task.sleep. After the delay, we update the labelText state variable on the main thread by calling await MainActor.run. This ensures the UI update happens safely on the main thread, which is required for SwiftUI views.

The button calls updateLabel() when tapped, triggering the background wait and then the UI update.

Final Result
Completed Screen
-------------------------
| MainActor UI Update Demo |
|-----------------------|
|                       |
|  Label: Waiting...     |
|                       |
|  [ Update Label ]      |
|                       |
-------------------------
User taps 'Update Label' button
Label text stays 'Waiting...' for 2 seconds
After 2 seconds, label text changes to 'Updated on MainActor!'
Stretch Goal
Add a loading spinner that shows while the background task runs and hides after update
💡 Hint
Use a @State Boolean to track loading state and show ProgressView conditionally in the UI