The Sendable protocol helps make sure data can be safely shared between different threads without causing problems.
When you want to pass data between different parts of your app running at the same time.
When you use Swift concurrency features like <code>async</code> and <code>await</code>.
When you want to avoid bugs caused by multiple threads changing data at once.
When you create custom types that will be used across threads.
When you want the compiler to help check your code for thread safety.
Syntax
Swift
struct MyData: Sendable {
var value: Int
}
Types that conform to Sendable promise they can be safely used across threads.
Most simple types like Int, String, and Bool are already Sendable.
Examples
A simple struct with only Sendable properties can conform to Sendable.
Swift
struct User: Sendable {
let name: Stringlet age: Int
}
Use @unchecked Sendable for classes when you promise to handle thread safety yourself.
Swift
class Counter: @unchecked Sendable {
varcount = 0
}
Functions can require parameters to be Sendable to ensure thread safety.
Swift
func updateData(data: some Sendable) async {
// safe to use data across threads
}
Sample Program
This program defines a Message struct that is Sendable. It then safely sends a message to an async function that prints it.
Swift
import Foundation
struct Message: Sendable {
let text: String
}
func printMessage(_ message: Message) async {
print("Message: \(message.text)")
}
@main
struct Main {
staticfunc main() async {
let msg = Message(text: "Hello from another thread!")
await printMessage(msg)
}
}
OutputSuccess
Important Notes
Marking a type Sendable helps the compiler check your code for thread safety.
Immutable types (ones that don't change) are easier to make Sendable.
Use @unchecked Sendable carefully; it skips safety checks.
Summary
Sendable means data can be safely shared between threads.
Use it with structs and classes to avoid threading bugs.
The compiler helps check your code when you use Sendable.
Practice
(1/5)
1. What does the Sendable protocol in Swift ensure?
easy
A. That a function runs asynchronously.
B. That a class can only be used on the main thread.
C. That a variable is immutable.
D. That data can be safely shared between threads without causing race conditions.
Solution
Step 1: Understand the purpose of Sendable
The Sendable protocol marks types that can be safely passed between threads without causing data races.
Step 2: Compare options with the definition
Only That data can be safely shared between threads without causing race conditions. correctly describes this safety guarantee. Other options describe unrelated concepts.
Final Answer:
That data can be safely shared between threads without causing race conditions. -> Option D
Quick Check:
Sendable = safe cross-thread data sharing [OK]
Hint: Sendable means safe to share data across threads [OK]
Common Mistakes:
Confusing Sendable with immutability
Thinking Sendable restricts to main thread only
Assuming Sendable makes functions async
2. Which of the following is the correct way to declare a struct as Sendable in Swift?
easy
A. struct Data { var value: Int } implements Sendable
B. struct Data: Sendable { var value: Int }
C. struct Data Sendable { var value: Int }
D. struct Data { var value: Int } : Sendable
Solution
Step 1: Recall Swift protocol conformance syntax
In Swift, a type conforms to a protocol by listing it after a colon following the type name.
Step 2: Match syntax to options
struct Data: Sendable { var value: Int } uses correct syntax: struct Data: Sendable { ... }. Others are invalid Swift syntax.
Final Answer:
struct Data: Sendable { var value: Int } -> Option B
Quick Check:
Protocol conformance uses colon after type name [OK]
Hint: Use colon after struct name to conform to Sendable [OK]
Common Mistakes:
Placing protocol after braces
Using 'implements' keyword (not Swift)
Omitting colon between type and protocol
3. What will happen when you try to compile this Swift code?
struct Counter: Sendable {
var count: Int
}
let counter = Counter(count: 5)
Task {
print(counter.count)
}
medium
A. It compiles and prints 5.
B. It causes a compile-time error because Counter is not Sendable.
C. It causes a runtime error due to thread safety violation.
D. It compiles but prints 0.
Solution
Step 1: Check if Counter conforms to Sendable
The struct explicitly conforms to Sendable and contains only an Int, which is Sendable.
Step 2: Understand Task usage
The Task runs asynchronously but can safely access counter because it is Sendable.
Final Answer:
It compiles and prints 5. -> Option A
Quick Check:
Sendable struct with Int prints value safely [OK]
Hint: Sendable structs with simple types compile and run safely [OK]
Common Mistakes:
Assuming compile error without checking conformance
Confusing runtime errors with compile errors
Thinking default structs are not Sendable
4. Identify the error in this Swift code using Sendable:
class DataHolder: Sendable {
var data: [Int]
init(data: [Int]) {
self.data = data
}
}
medium
A. Missing explicit Sendable conformance on Array.
B. Class cannot conform to Sendable at all.
C. Array<Int> is not Sendable by default, causing a compile error.
D. No error; code compiles fine.
Solution
Step 1: Check Sendable conformance for class with mutable property
Classes with mutable stored properties like arrays are not automatically Sendable.
Step 2: Understand why Array<Int> is not Sendable by default
Array is a reference type and mutable, so compiler disallows automatic Sendable conformance without extra guarantees.
Final Answer:
Array<Int> is not Sendable by default, causing a compile error. -> Option C