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.