Bird
Raised Fist0
iOS Swiftmobile~20 mins

MainActor for UI updates in iOS Swift - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
MainActor Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ ui_behavior
intermediate
2:00remaining
What happens when you update UI without MainActor?
Consider this Swift async function updating a UILabel text without @MainActor. What is the likely outcome?
iOS Swift
func updateLabel() async {
  label.text = "Hello"
}
AThe label text updates but only after a delay of several seconds.
BThe app may crash or show UI glitches due to thread violation.
CThe UI updates smoothly without any issues.
DThe code will not compile because label.text must be updated on MainActor.
Attempts:
2 left
💡 Hint
UI updates must happen on the main thread to avoid problems.
📝 Syntax
intermediate
2:00remaining
Which function declaration correctly ensures UI updates on the main thread?
Select the correct Swift function declaration that guarantees UI updates run on the main thread using MainActor.
A
@MainActor func updateUI() async {
  label.text = "Hi"
}
B
func updateUI() @MainActor async {
  label.text = "Hi"
}
C
func updateUI() async @MainActor {
  label.text = "Hi"
}
D
func updateUI() async {
  label.text = "Hi"
}
Attempts:
2 left
💡 Hint
The @MainActor attribute goes before the func keyword or before the function name.
❓ lifecycle
advanced
2:00remaining
Why use @MainActor on a ViewModel class for UI updates?
You have a ViewModel class that updates UI-bound properties. Why is marking the entire class with @MainActor beneficial?
AIt forces all methods and properties to run on the main thread, preventing UI thread bugs.
BIt makes the class run faster by using multiple threads.
CIt disables concurrency features to simplify code.
DIt automatically updates the UI without any code changes.
Attempts:
2 left
💡 Hint
UI updates must happen on the main thread to avoid crashes.
🔧 Debug
advanced
2:00remaining
Identify the cause of a crash in this async UI update code
This Swift code crashes sometimes. What is the cause?
iOS Swift
func fetchData() async {
  let data = await loadData()
  label.text = data
}

func loadData() async -> String {
  // Simulate network delay
  try? await Task.sleep(nanoseconds: 1_000_000_000)
  return "Loaded"
}
AThe label outlet is nil causing the crash.
BThe Task.sleep call throws an error causing the crash.
CThe await keyword is used incorrectly inside fetchData.
DUpdating label.text off the main thread causes the crash.
Attempts:
2 left
💡 Hint
UI updates must happen on the main thread even after async calls.
🧠 Conceptual
expert
2:00remaining
What does @MainActor guarantee in Swift concurrency?
Choose the best description of what @MainActor guarantees when applied to a function or class.
A@MainActor guarantees code runs on any thread but prioritizes the main thread.
B@MainActor guarantees that all code runs on the main thread synchronously.
C@MainActor guarantees that code runs on the main thread and serializes access to prevent data races.
D@MainActor guarantees code runs on a background thread to avoid blocking UI.
Attempts:
2 left
💡 Hint
Think about thread safety and UI updates.

Practice

(1/5)
1. What is the main purpose of using @MainActor in Swift UI code?
easy
A. To ensure UI updates happen on the main thread
B. To run background tasks faster
C. To prevent memory leaks
D. To encrypt user data

Solution

  1. Step 1: Understand UI thread requirements

    UI updates must happen on the main thread to avoid crashes and keep the app smooth.
  2. Step 2: Role of @MainActor

    @MainActor ensures the annotated code runs on the main thread, making UI updates safe.
  3. Final Answer:

    To ensure UI updates happen on the main thread -> Option A
  4. Quick Check:

    MainActor = UI updates on main thread [OK]
Hint: MainActor always means UI code runs on main thread [OK]
Common Mistakes:
  • Thinking @MainActor speeds up background tasks
  • Confusing @MainActor with memory management
  • Assuming @MainActor encrypts data
2. Which of the following is the correct way to declare a function that updates UI using MainActor in Swift?
easy
A. func updateUI() { @MainActor /* code */ }
B. func updateUI() @MainActor { /* code */ }
C. func @MainActor updateUI() { /* code */ }
D. @MainActor func updateUI() { /* code */ }

Solution

  1. Step 1: Recall correct syntax for @MainActor

    @MainActor is an attribute placed before the function declaration.
  2. Step 2: Check each option

    @MainActor func updateUI() { /* code */ } correctly places @MainActor before the function name.
  3. Final Answer:

    @MainActor func updateUI() { /* code */ } -> Option D
  4. Quick Check:

    @MainActor before func = correct syntax [OK]
Hint: @MainActor goes before func keyword [OK]
Common Mistakes:
  • Placing @MainActor after func name
  • Putting @MainActor inside function body
  • Using @MainActor as a suffix
3. Consider this Swift code snippet:
@MainActor
class ViewModel {
  var count = 0

  func increment() {
    count += 1
  }
}

let vm = ViewModel()
Task {
  await vm.increment()
  print(vm.count)
}
What will be printed?
medium
A. Compilation error
B. 0
C. 1
D. Runtime crash

Solution

  1. Step 1: Understand @MainActor on class

    The class ViewModel is marked @MainActor, so its methods and properties are isolated to the main actor.
  2. Step 2: Analyze the code

    await vm.increment() correctly increments count. Accessing vm.count inside the Task closure is safe because it's running on the main actor context.
  3. Final Answer:

    1 -> Option C
  4. Quick Check:

    Accessing @MainActor properties within the actor context is allowed [OK]
Hint: @MainActor properties can be accessed safely within actor context without await [OK]
Common Mistakes:
  • Thinking it prints 1 and forgetting await on print(vm.count)
  • Expecting runtime crash instead of compile error
  • Believing count stays 0 due to async context
4. You have this Swift function:
func updateLabel() {
  label.text = "Hello"
}
When called from a background thread, the app crashes. How can you fix it using MainActor?
medium
A. Add @MainActor before the function declaration
B. Call updateLabel() inside DispatchQueue.global()
C. Remove the function and update label directly
D. Wrap label update inside DispatchQueue.main.async without @MainActor

Solution

  1. Step 1: Identify cause of crash

    UI updates must happen on main thread; background thread causes crash.
  2. Step 2: Use @MainActor to fix

    Adding @MainActor before function ensures it runs on main thread, preventing crash.
  3. Final Answer:

    Add @MainActor before the function declaration -> Option A
  4. Quick Check:

    @MainActor fixes UI thread crash [OK]
Hint: Use @MainActor to run UI code on main thread automatically [OK]
Common Mistakes:
  • Using global queue instead of main queue
  • Updating UI directly from background thread
  • Ignoring thread safety causing crashes
5. You want to update a SwiftUI view's text label from a background task safely. Which approach correctly uses @MainActor and async/await to update the UI?
hard
A. Use DispatchQueue.global().async to update the label
B. Declare the update function with @MainActor and call it with await inside the background task
C. Call the update function directly from the background thread without @MainActor
D. Update the label inside the background task without any special handling

Solution

  1. Step 1: Understand UI update rules

    UI updates must happen on main thread to avoid crashes and glitches.
  2. Step 2: Use @MainActor with async/await

    Marking the update function with @MainActor ensures it runs on main thread. Calling it with await from background task switches context safely.
  3. Step 3: Evaluate other options

    Options A, B, and D update UI from background thread causing errors or crashes.
  4. Final Answer:

    Declare the update function with @MainActor and call it with await inside the background task -> Option B
  5. Quick Check:

    @MainActor + await = safe UI update [OK]
Hint: Use @MainActor function called with await for UI updates [OK]
Common Mistakes:
  • Updating UI directly from background thread
  • Ignoring await when calling @MainActor function
  • Using global queue for UI updates
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard