Actor Isolation and nonisolated
Reason about isolation boundaries.
Actor Isolation and nonisolated is a free Swift Academy lesson on CoddyKit. This is lesson 3 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, and your progress syncs across the web and the CoddyKit app. The Swift Academy course includes 4 lessons in total.
What Is Actor Isolation?
Actor isolation means an actor’s mutable state can only be touched by code running on that actor.
The runtime serializes access so two tasks never mutate the state simultaneously, eliminating data races.
actor Counter {
private var value = 0
func increment() { value += 1 }
}Calling Into an Actor
From outside the actor, accessing isolated members is asynchronous. You must await because the call may suspend until the actor is free.
let counter = Counter()
func useCounter() async {
await counter.increment()
}Inside the Actor: Synchronous
Within the actor’s own methods, you are already isolated, so you access state synchronously—no await needed for self.
actor Counter {
private var value = 0
func incrementTwice() {
value += 1 // synchronous: already isolated
value += 1
}
}nonisolated Members
Mark a member nonisolated when it does not touch mutable state. Such members run synchronously from anywhere, with no await.
This is ideal for computed values built only from immutable data.
actor User {
let id: Int
var sessionCount = 0
init(id: Int) { self.id = id }
nonisolated var label: String { "User #\(id)" }
}Why nonisolated Is Safe
A nonisolated member may only read immutable (let) or otherwise Sendable state.
The compiler rejects any attempt to access mutable isolated state from a nonisolated context.
actor User {
let id: Int
var sessionCount = 0
init(id: Int) { self.id = id }
// Error: cannot read mutable sessionCount here
// nonisolated var bad: Int { sessionCount }
}nonisolated and Protocols
nonisolated is essential when an actor conforms to a synchronous protocol. The protocol method cannot be async, so it must avoid isolated state.
actor Item: CustomStringConvertible {
let name: String
init(name: String) { self.name = name }
nonisolated var description: String { "Item: \(name)" }
}The MainActor
@MainActor is a global actor that isolates code to the main thread. UI updates belong here.
Annotate types, methods, or properties to pin them to the main actor.
@MainActor
final class ViewModel {
var title = "Hello"
func refresh() { title = "Updated" }
}Hopping Between Actors
When you call from one actor to another, the runtime hops executors and suspends. That suspension is exactly where await appears.
actor Database { func load() -> Int { 42 } }
@MainActor
func show(_ db: Database) async {
let v = await db.load() // hop to db actor
print(v) // hop back to main
}Actor Reentrancy
Actors are reentrant: when a method awaits, the actor may run other queued work before the await resumes.
State you read before an await may have changed after it. Re-check assumptions after suspension points.
actor Store {
var ready = false
func prepare() async {
ready = false
await Task.yield() // other calls may run here
ready = true
}
}isolated Parameters
A function can take an isolated actor parameter, running its body on that actor without being a member of it.
func bump(on counter: isolated Counter) {
// runs isolated to counter; synchronous access
}Global Actors for Subsystems
You can define your own global actor to isolate a whole subsystem (e.g. a rendering pipeline) onto a single executor.
@globalActor
actor RenderActor {
static let shared = RenderActor()
}
@RenderActor func draw() { }Quick Check: Isolation
Test your understanding of actor isolation.
Recap: Actor Isolation and nonisolated
Actor isolation serializes access to mutable state; cross-actor calls are async and require await. nonisolated members opt out of isolation but may only read immutable/Sendable state, which is vital for synchronous protocol conformance.
@MainActor pins code to the main thread, actors are reentrant (state can change across await), and global actors isolate whole subsystems. Mastering these rules is the core of safe concurrency.
Learn Swift with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 122
- Lessons
- 409
Frequently Asked Questions
Is the “Actor Isolation and nonisolated” lesson free?
Yes — any 3 lessons of the Swift Academy learning path, including “Actor Isolation and nonisolated”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Swift Academy course includes 4 lessons in total.
What will I learn in “Actor Isolation and nonisolated”?
Reason about isolation boundaries. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Swift Academy?
No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.
How long does the “Actor Isolation and nonisolated” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Swift Academy lesson?
Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- The Data Race Problem
- The Sendable Protocol
- Actor Isolation and nonisolated
- Migrating to Strict Concurrency