Bird
Raised Fist0
Swiftprogramming~30 mins

Global actors (@MainActor) in Swift - Mini Project: Build & Apply

Choose your learning style10 modes available
Using Global Actors with @MainActor in Swift
📖 Scenario: You are building a simple Swift program that manages a shared counter. This counter must be updated safely on the main thread to avoid conflicts in a user interface environment.
🎯 Goal: Learn how to use the @MainActor global actor to ensure that updates to a shared resource happen on the main thread.
📋 What You'll Learn
Create a class called Counter with a property value initialized to 0
Add a method increment() to increase value by 1
Mark the Counter class with the @MainActor attribute
Create an instance of Counter and call increment() three times
Print the final value of the counter
💡 Why This Matters
🌍 Real World
In apps with user interfaces, updating shared data on the main thread prevents crashes and keeps UI smooth.
💼 Career
Understanding @MainActor is important for Swift developers working on iOS/macOS apps to write safe, concurrent code.
Progress0 / 4 steps
1
Create the Counter class
Create a class called Counter with a property value set to 0.
Swift
Hint

Use class Counter { var value = 0 } to define the class and property.

2
Add increment() method
Add a method called increment() inside the Counter class that increases value by 1.
Swift
Hint

Define func increment() { value += 1 } inside the class.

3
Mark Counter with @MainActor
Add the @MainActor attribute before the Counter class declaration to make it a global actor isolated class.
Swift
Hint

Place @MainActor on the line above class Counter.

4
Use Counter and print value
Create an instance of Counter called counter. Call increment() three times on counter. Then print counter.value.
Swift
Hint

Use let counter = Counter(), call counter.increment() three times, then print(counter.value).

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