Sendable & Data-Race Safety
Swift 6 makes data-race safety a compile-time guarantee. Learn the Sendable protocol, @Sendable closures, actor isolation , @MainActor , sending values across isolation domains, nonisolated , and why the compiler now enforces all of this.
Learn Sendable & Data-Race Safety in our free Swift course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Swift course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
1️⃣ The Sendable Protocol
Sendable marks a type as safe to share across concurrency domains. Value types built from Sendable members conform automatically, so most structs are already safe.
2️⃣ @Sendable Closures
An @Sendable closure may only capture Sendable values, so it is safe to run concurrently. A Task 's body is exactly such a closure.
3️⃣ Actor Isolation, @MainActor, nonisolated
An actor isolates mutable state, making it safely shareable. @MainActor pins code to the main thread; nonisolated opts a member out so it needs no await .
Your turn. Fill in the safety protocol and the closure attribute.
📋 Quick Reference
Wrap a shared counter in an actor so many tasks can update it safely.
Practice quiz
What does the Sendable protocol indicate about a type?
- It is safe to share across concurrency domains
- It is a class
- It is faster
- It can be serialized to JSON
Answer: It is safe to share across concurrency domains. Sendable marks a type as safe to pass across actor or task boundaries without data races.
Which kind of type is automatically Sendable when its members are Sendable?
- A global variable
- A class with mutable state
- A value type like a struct of Sendable values
- Any closure
Answer: A value type like a struct of Sendable values. Value types such as structs and enums made of Sendable members get Sendable conformance for free.
What does marking a closure @Sendable promise?
- It never returns
- It captures only values safe to use across concurrency domains
- It is async
- It runs on the main thread
Answer: It captures only values safe to use across concurrency domains. An @Sendable closure may only capture Sendable values, so it is safe to run concurrently.
What problem do actors solve in relation to Sendable?
- They format strings
- They speed up JSON
- They replace structs
- They isolate mutable state so it is safe to share concurrently
Answer: They isolate mutable state so it is safe to share concurrently. An actor isolates its mutable state, providing a safe way to share reference-type state across tasks.
What does @MainActor guarantee about annotated code?
- It runs on the main actor, typically for UI work
- It is private
- It never suspends
- It runs on a background thread
Answer: It runs on the main actor, typically for UI work. @MainActor pins code to the main actor, which is where UI updates must happen.
What does the nonisolated keyword do on an actor member?
- Deletes it
- Opts a member out of the actor's isolation so it needs no await
- Makes it async
- Makes it isolated
Answer: Opts a member out of the actor's isolation so it needs no await. nonisolated removes a member from actor isolation, so callers can use it synchronously without await.
Under Swift 6 strict concurrency, data races are...
- Allowed at runtime
- Ignored
- Only warnings forever
- Caught by the compiler at build time
Answer: Caught by the compiler at build time. Swift 6 makes data-race safety a compile-time guarantee, turning many races into build errors.
Why might a class NOT be automatically Sendable?
- Classes are too fast
- Classes cannot conform to protocols
- It can have shared mutable reference state that risks races
- It has no methods
Answer: It can have shared mutable reference state that risks races. A class is a reference type with potentially shared mutable state, so it is not implicitly Sendable.
How can you assert a type is Sendable when you have verified its safety manually?
- @raw
- @unchecked Sendable
- @forceSendable
- @safe
Answer: @unchecked Sendable. Conforming with @unchecked Sendable tells the compiler you guarantee safety it cannot prove, such as with an internal lock.
Crossing from one isolation domain to another with a non-Sendable value causes...
- A compiler diagnostic under strict concurrency
- Nothing
- Faster code
- Automatic copying always
Answer: A compiler diagnostic under strict concurrency. Sending a non-Sendable value across isolation boundaries is flagged by the compiler to prevent races.