A Guide to Swift Actors

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

A Guide to Swift Actors

A Private Workshop

Before actors, managing shared data in concurrent code was a headache. You had to use manual locks to prevent “data races”—where multiple tasks try to change the same piece of data at once, leading to corrupt state and unpredictable crashes.

Actor Isolation: Crossing the Boundary with await

Because an actor protects its internal state, you can’t just barge in from the outside. Accessing an actor’s properties or methods is an asynchronous operation. You have to send a request and wait for your turn to get access. This “waiting” is what the await keyword signifies.

Code Example: The Counter Actor

This simple actor safely manages a number. Outside code must await to interact with its methods.

The Express Lane: nonisolated

What if a property or method doesn’t actually touch the actor’s private state? It would be inefficient to make callers wait in line for no reason.

Code Example: Getting Static Information

The Big Surprise: Reentrancy

Here’s the trickiest part of actors. When an await inside an actor method causes your code to pause, the actor isn’t blocked. It’s free to process other work from the queue. This is called reentrancy. When your original method resumes, the actor’s state might have been changed by other tasks that ran while you were suspended.

The Safe Pattern: Commit Before You Suspend

To avoid reentrancy bugs, follow this critical rule: Modify the actor’s state to reflect your action before the first await.

Code Example: The Fixed TicketOffice

This version is safe. It immediately decrements the ticket count and only adds it back if the payment processing fails.

Who Runs Where: @MainActor and Global Actors

Sometimes, you need to ensure code runs on a specific thread or that different types share the same actor for protection.

Code Example: A Global Actor for Disk Access

Summary Checklist

  • Model actors as private workshops to protect data.
  • Use await to wait your turn to safely enter an actor.
  • Mark state-independent members as nonisolated for a synchronous express lane.
  • Treat every await inside an actor as a potential state change. The world can change while you’re paused.
  • Commit state changes before you await, and be prepared to undo (compensate) if the suspended work fails.
  • Use @MainActor for all UI updates. No exceptions.
See forum comments
Download course materials from Github
Previous: Introduction Next: Swift Actors Demo from Network to UI