Bird
Raised Fist0
Swiftprogramming~5 mins

Global actors (@MainActor) in Swift

Choose your learning style10 modes available
Introduction

Global actors help keep your app's main work safe and organized by making sure certain code runs only on the main thread. This is important for updating the user interface smoothly.

When you want to update the app's user interface safely.
When you need to run code that must not run at the same time as other main thread tasks.
When you want to mark functions or properties to always run on the main thread.
When you want to avoid bugs caused by running UI code on background threads.
Syntax
Swift
@MainActor
func yourFunction() {
    // code that runs on the main thread
}

@MainActor is a built-in global actor in Swift for the main thread.

Use it before functions, properties, or classes to ensure they run on the main thread.

Examples
This function will always run on the main thread.
Swift
@MainActor
func updateUI() {
    print("Updating UI on main thread")
}
The property and function are marked to run on the main thread, keeping UI data safe.
Swift
class ViewModel {
    @MainActor var title: String = ""

    @MainActor func changeTitle(newTitle: String) {
        title = newTitle
    }
}
The whole class runs on the main thread, so all its methods do too.
Swift
@MainActor
class ViewController {
    func showAlert() {
        print("Showing alert on main thread")
    }
}
Sample Program

This program shows a function marked with @MainActor to update UI safely. The async function calls it with await to ensure it runs on the main thread.

Swift
import Foundation

@MainActor
func updateLabel() {
    print("Label updated on main thread")
}

func doWork() async {
    print("Starting work")
    await updateLabel()
    print("Work done")
}

@main
struct Main {
    static func main() async {
        await doWork()
    }
}
OutputSuccess
Important Notes

Use await when calling @MainActor functions from outside the main actor.

@MainActor helps prevent crashes caused by updating UI from background threads.

Marking a whole class with @MainActor means all its code runs on the main thread automatically.

Summary

@MainActor ensures code runs on the main thread for UI safety.

Use it on functions, properties, or classes that interact with the UI.

Call @MainActor code with await from other threads.

Practice

(1/5)
1. What is the main purpose of using @MainActor in Swift?
easy
A. To create background tasks without blocking the UI
B. To make code run faster by using multiple threads
C. To encrypt data automatically
D. To ensure code runs on the main thread for UI safety

Solution

  1. Step 1: Understand the role of @MainActor

    @MainActor marks code to run on the main thread, which is important for UI updates.
  2. Step 2: Compare options with this purpose

    Only To ensure code runs on the main thread for UI safety correctly states that @MainActor ensures code runs on the main thread for UI safety.
  3. Final Answer:

    To ensure code runs on the main thread for UI safety -> Option D
  4. Quick Check:

    @MainActor purpose = UI safety on main thread [OK]
Hint: Remember: @MainActor means run on main thread for UI [OK]
Common Mistakes:
  • Thinking @MainActor speeds up code
  • Confusing @MainActor with background threading
  • Assuming @MainActor encrypts data
2. Which of the following is the correct way to declare a function that runs on the main actor?
easy
A. @MainActor func updateUI() { }
B. func @MainActor updateUI() { }
C. func updateUI() @MainActor { }
D. func updateUI() mainActor { }

Solution

  1. Step 1: Recall correct syntax for @MainActor

    The attribute @MainActor is placed before the function declaration.
  2. Step 2: Check each option's syntax

    @MainActor func updateUI() { } correctly places @MainActor before the function name. Others have incorrect placement or syntax.
  3. Final Answer:

    @MainActor func updateUI() { } -> Option A
  4. Quick Check:

    @MainActor syntax = before func [OK]
Hint: Put @MainActor right before func keyword [OK]
Common Mistakes:
  • Placing @MainActor after function name
  • Using invalid keywords like mainActor without @
  • Inserting @MainActor inside function parentheses
3. Consider this Swift code snippet:
@MainActor
class ViewModel {
    func update() {
        print("Updated on main thread")
    }
}

func backgroundTask() async {
    let vm = await ViewModel()
    await vm.update()
}

Task {
    await backgroundTask()
}
What will be printed when this code runs?
medium
A. No output due to error
B. Updated on main thread
C. Updated on background thread
D. Runtime crash due to thread violation

Solution

  1. Step 1: Understand @MainActor on ViewModel class

    The entire ViewModel class runs on the main thread because of @MainActor.
  2. Step 2: Analyze the call to update() with await

    Calling await vm.update() from backgroundTask correctly switches to main thread and runs update(), printing the message.
  3. Final Answer:

    Updated on main thread -> Option B
  4. Quick Check:

    @MainActor enforces main thread execution [OK]
Hint: await switches to main thread for @MainActor code [OK]
Common Mistakes:
  • Expecting no output due to async
  • Thinking update runs on background thread
  • Assuming thread violation crash
4. This code produces a compile error. What is the mistake?
class DataManager {
    @MainActor func save() {
        print("Saving data")
    }
}

func run() {
    let dm = DataManager()
    dm.save()
}
medium
A. Cannot use @MainActor on class methods
B. Function save() must be static
C. Missing await when calling @MainActor async function
D. DataManager must be marked @MainActor

Solution

  1. Step 1: Identify @MainActor function requirements

    Functions marked @MainActor are asynchronous and must be called with await.
  2. Step 2: Check call to save()

    Calling dm.save() without await causes a compile error because save() is async under @MainActor.
  3. Final Answer:

    Missing await when calling @MainActor async function -> Option C
  4. Quick Check:

    @MainActor functions require await calls [OK]
Hint: Always use await when calling @MainActor functions [OK]
Common Mistakes:
  • Calling @MainActor functions without await
  • Thinking @MainActor disallows methods on classes
  • Believing @MainActor requires static functions
5. You want to create a Swift class that updates UI labels safely from any thread. Which is the best way to ensure all UI updates happen on the main thread using @MainActor?
hard
A. Mark the class with @MainActor and call its methods with await from any thread
B. Mark each UI label property with @MainActor individually
C. Use DispatchQueue.global() inside the class methods
D. Mark the class as final and use synchronous methods only

Solution

  1. Step 1: Understand @MainActor usage for UI safety

    Marking the whole class with @MainActor ensures all its code runs on the main thread.
  2. Step 2: Consider calling methods with await

    Calling methods with await from any thread safely switches to main thread for UI updates.
  3. Step 3: Evaluate other options

    Marking individual properties is less effective; DispatchQueue.global() runs on background thread; final keyword does not ensure thread safety.
  4. Final Answer:

    Mark the class with @MainActor and call its methods with await from any thread -> Option A
  5. Quick Check:

    @MainActor class + await calls = safe UI updates [OK]
Hint: Use @MainActor on class and await calls for UI safety [OK]
Common Mistakes:
  • Marking only properties instead of class
  • Using background queues for UI updates
  • Ignoring async/await with @MainActor
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