What is an actor?

Concurrency Mid-level Swift 5.5+ iOS 15+ Reviewed By Alok Singh

Pick the fix

func tap() { counter.increment() } fails: actor-isolated method can't be called from a nonisolated context. Which fix is right?

actor Counter {
    private(set) var value = 0
    func increment() { value += 1 }
}
let counter = Counter()
func tap() { counter.increment() }
Options
Hint 1 of 2

What does a caller outside the actor have to do?

Hint 2 of 2

What does nonisolated give up?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Make tap() async and write await counter.increment()

Correct. Calls from outside the actor must await their turn.

Why not the others?
  • B Mark increment() as nonisolated. A nonisolated method can't mutate value, so this doesn't compile either.
  • C Write counter.value += 1 directly. value is isolated too, so this fails in the same way.
  • D Turn Counter into a class marked @unchecked Sendable. It compiles, but you have removed the protection and created a data race.

30-second answer

An actor is a reference type that protects its mutable state by running one piece of its code at a time. Code outside the actor can't touch that state synchronously; it must await a call, because the call may have to wait its turn. This removes data races at compile time without manual locks.

Practise saying it · 45 s. No recording, just a timer

Explain what an actor is and why callers await it.

Say your answer out loud, then check which of these points you covered:

  • Protects mutable state with serialized access
  • Outside calls need await
  • Not a dedicated thread
  • Mentions reentrancy

Deep dive

Inside the actor, methods access state synchronously, with no await.

nonisolated members don't touch isolated state and can be called synchronously from anywhere.

Actors are reentrant: at each await inside an actor method, other calls may run.

Global actors such as @MainActor apply the same idea to code spread across many types.

Common mistakes

  • Thinking actors run on their own dedicated thread.
  • Adding @unchecked Sendable to a class instead of using an actor.
  • Forgetting reentrancy and checking state before an await.

Senior take & follow-ups

Seniors explain actors as 'serialized access, not a thread', and mention reentrancy before being asked.

Follow-up questions

Think of your answer first, then open the hint.

  1. Can an actor's method be synchronous?

    Show hint

    Yes. It is synchronous inside, but callers outside still await it.

  2. When would you choose a Mutex over an actor?

    Show hint

    When callers must stay synchronous, like a tiny counter.

Suggest a fix if something here is wrong or out of date.