Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungRefreshed repository pull requests page generally available(22.09.2026 um 03:25 Uhr)
Sichere ProgrammierungThe Joy of Learning the Basics Again(22.09.2026 um 03:28 Uhr)
Sichere ProgrammierungZero-Code OpenTelemetry Tracing for Dagster(22.09.2026 um 03:39 Uhr)
Linux Tipps & Hardening`prime-all`(22.09.2026 um 02:28 Uhr)
IT Security Toolsopensoho v0.15.2(22.09.2026 um 03:33 Uhr)
IT Security NachrichtenUS Proposes AI Incident Alert System in Talks With China, Bessent Says(22.09.2026 um 04:01 Uhr)
Sichere ProgrammierungRefreshed repository pull requests page generally available(22.09.2026 um 03:25 Uhr)
Sichere ProgrammierungThe Joy of Learning the Basics Again(22.09.2026 um 03:28 Uhr)
Sichere ProgrammierungZero-Code OpenTelemetry Tracing for Dagster(22.09.2026 um 03:39 Uhr)
Linux Tipps & Hardening`prime-all`(22.09.2026 um 02:28 Uhr)
IT Security Toolsopensoho v0.15.2(22.09.2026 um 03:33 Uhr)
IT Security NachrichtenUS Proposes AI Incident Alert System in Talks With China, Bessent Says(22.09.2026 um 04:01 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Swift Sendable: Mastering Thread Safety in iOS Development

When working with Swift concurrency, developers often encounter compiler warnings about "sending non-Sendable types across actor boundaries." These warnings aren't just noise—they're preventing serious runtime crashes and data corruption. U…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

When working with Swift concurrency, developers often encounter compiler warnings about "sending non-Sendable types across actor boundaries." These warnings aren't just noise—they're preventing serious runtime crashes and data corruption. Understanding Sendable is crucial for building reliable concurrent iOS applications.



When you mark something as Sendable, you're telling Swift:




This is safe to send from one place to another without special precautions.




The ability to safely "send" data across concurrency boundaries.






The Core Problem Sendable Solves



Modern iOS apps need to perform multiple operations simultaneously: downloading data, updating the UI, processing images, and handling user interactions. Without proper synchronization, these concurrent operations can interfere with each other, leading to unpredictable behavior.



Consider this seemingly innocent code:




class ShoppingCart {
var items: [Product] = []
var totalPrice: Double = 0.0

func addItem(_ product: Product) {
items.append(product)
totalPrice += product.price
}

func removeItem(at index: Int) {
let removedProduct = items.remove(at: index)
totalPrice -= removedProduct.price
}
}

// Multiple parts of the app accessing the same cart
let cart = ShoppingCart()

// Background task adding items
Task {
cart.addItem(Product(name: "iPhone", price: 999.0))
}

// Another task removing items
Task {
if !cart.items.isEmpty {
cart.removeItem(at: 0) // Potential crash!
}
}

// Main thread displaying total
print("Total: $\(cart.totalPrice)") // Unpredictable value!






This code contains multiple data races. The items array and totalPrice property are being modified from different concurrent contexts simultaneously, which can result in:




  • Array index out of bounds crashes

  • Incorrect total calculations

  • Memory corruption

  • Unpredictable app behavior






Understanding the Sendable Concept



Sendable is a protocol that marks types as safe to transfer across concurrency boundaries. When a type conforms to Sendable, the compiler guarantees it can be safely shared between different actors, tasks, or threads without causing data races.



The key insight is that not all data is safe to share concurrently. Sendable helps distinguish between:





  • Safe data: Can be shared without synchronization


  • Unsafe data: Requires careful handling to prevent races



Think of Sendable as a safety certification that tells the compiler: "This type won't cause problems when used concurrently."






Types That Are Automatically Sendable



Swift automatically considers certain types as Sendable because they're inherently thread-safe:






Value Types with Sendable Properties






// Automatically Sendable - all properties are immutable and Sendable
struct User: Sendable {
let id: UUID
let name: String
let email: String
let registrationDate: Date
}

// Also automatically Sendable
struct APIResponse: Sendable {
let statusCode: Int
let data: Data
let timestamp: Date
}









Enums with Sendable Associated Values






enum NetworkResult: Sendable {
case success(Data)
case failure(NetworkError)
case loading
}

enum UserAction: Sendable {
case login(username: String, password: String)
case logout
case updateProfile(User)
}









Built-in Types



Most of Swift's fundamental types are Sendable:





  • Int, Double, Bool, String


  • Array<T> where T is Sendable


  • Dictionary<K, V> where both K and V are Sendable


  • Optional<T> where T is Sendable






Making Custom Types Sendable






Structs and Enums



For value types, ensuring Sendable conformance is straightforward—all stored properties must be Sendable:




// ✅ Valid Sendable struct
struct BlogPost: Sendable {
let title: String
let content: String
let author: User // User must also be Sendable
let publishDate: Date
let tags: [String]
}

// ❌ Invalid - contains non-Sendable property
struct InvalidPost {
let title: String
let databaseConnection: DatabaseManager // Class, not Sendable
}

// ✅ Fixed version
struct ValidPost: Sendable {
let title: String
let databaseConnectionID: String // Store identifier instead
}









Classes - The Complex Case



Classes are reference types, making them inherently more dangerous for concurrent access. There are several strategies to make classes Sendable:






Immutable Classes






final class Configuration: Sendable {
let apiKey: String
let baseURL: URL
let timeout: TimeInterval
let maxRetries: Int

init(apiKey: String, baseURL: URL, timeout: TimeInterval, maxRetries: Int) {
self.apiKey = apiKey
self.baseURL = baseURL
self.timeout = timeout
self.maxRetries = maxRetries
}
}









Thread-Safe Classes with Internal Synchronization






final class AtomicCounter: Sendable {
private let lock = NSLock()
private var _value: Int = 0

var value: Int {
lock.withLock { _value }
}

func increment() {
lock.withLock { _value += 1 }
}

func decrement() {
lock.withLock { _value -= 1 }
}
}

extension NSLock {
func withLock<T>(_ body: () throws -> T) rethrows -> T {
lock()
defer { unlock() }
return try body()
}
}









Actors: The Natural Sendable Solution



Actors provide built-in thread safety and are automatically Sendable:




actor DataCache {
private var cache: [String: Any] = [:]
private var lastUpdated: [String: Date] = [:]

func store(key: String, value: Any) {
cache[key] = value
lastUpdated[key] = Date()
}

func retrieve(key: String) -> Any? {
return cache[key]
}

func clearExpired(olderThan timeInterval: TimeInterval) {
let cutoffDate = Date().addingTimeInterval(-timeInterval)
let expiredKeys = lastUpdated.compactMap { key, date in
date < cutoffDate ? key : nil
}

for key in expiredKeys {
cache.removeValue(forKey: key)
lastUpdated.removeValue(forKey: key)
}
}
}









Function Parameters and Sendable



Functions that work with concurrent code should specify Sendable requirements:




// Function parameter must be Sendable
func processInBackground<T: Sendable>(_ data: T) async -> ProcessedResult {
// Safe to use 'data' across await boundaries
await someAsyncOperation()
return ProcessedResult(from: data)
}

// Closure must be Sendable for concurrent execution
func executeAsync(
operation: @Sendable @escaping () async throws -> Void
) {
Task {
try await operation()
}
}

// Generic constraint ensures type safety
func cacheResult<T: Sendable & Codable>(
key: String,
value: T
) async {
let cache = DataCache()
await cache.store(key: key, value: value)
}









Common Pitfalls and Solutions






Mutable Properties in Structs






// ❌ Problematic - mutable properties can cause issues
struct ProblemUser {
var name: String // Mutable property
let id: UUID
}

// ✅ Better - immutable properties
struct SafeUser: Sendable {
let name: String
let id: UUID
}

// ✅ Alternative - functional updates
extension SafeUser {
func withName(_ newName: String) -> SafeUser {
SafeUser(name: newName, id: id)
}
}









Collections of Non-Sendable Types






// ❌ Array of non-Sendable elements
class DatabaseConnection {
func execute(_ query: String) { /* ... */ }
}

let connections: [DatabaseConnection] = [] // Not Sendable

// ✅ Use Sendable identifiers instead
struct ConnectionID: Sendable {
let id: UUID
}

let connectionIDs: [ConnectionID] = [] // Sendable

// ✅ Or use actor for managing connections
actor ConnectionPool {
private var connections: [UUID: DatabaseConnection] = [:]

func getConnection(id: UUID) -> DatabaseConnection? {
return connections[id]
}
}









Closures Capturing Non-Sendable Values






class NonSendableService {
func performOperation() { /* ... */ }
}

let service = NonSendableService()

// ❌ Capturing non-Sendable value
Task {
service.performOperation() // Compiler warning
}

// ✅ Extract Sendable data first
let operationData = service.extractSendableData()
Task {
await processData(operationData)
}

// ✅ Or use actor to wrap the service
actor ServiceWrapper {
private let service = NonSendableService()

func performOperation() {
service.performOperation()
}
}









Simple Practical Examples



Here are some concise examples showing proper Sendable usage:




// Basic API request model
struct APIRequest: Sendable {
let url: URL
let method: String
let headers: [String: String]
}

// Simple data cache using actor
actor DataCache {
private var cache: [String: Data] = [:]

func store(key: String, data: Data) {
cache[key] = data
}

func retrieve(key: String) -> Data? {
return cache[key]
}
}

// Sendable result type
enum Result<T: Sendable>: Sendable {
case success(T)
case failure(Error)
}









Debugging Sendable Issues



When encountering Sendable-related compiler errors, follow this systematic approach:






1. Identify the Non-Sendable Type






// Compiler error: "Cannot pass argument of non-Sendable type..."
struct MyStruct {
let manager: DatabaseManager // This is the problem
}

// Fix: Replace with Sendable alternative
struct MyStruct: Sendable {
let managerID: String // Sendable identifier
}









2. Check Property Mutability






// Problem: Mutable properties
struct Settings {
var theme: String // Mutable
var notifications: Bool // Mutable
}

// Solution: Make immutable or use functional updates
struct Settings: Sendable {
let theme: String
let notifications: Bool

func withTheme(_ newTheme: String) -> Settings {
Settings(theme: newTheme, notifications: notifications)
}
}









3. Verify Generic Constraints






// Problem: Generic type without Sendable constraint
func process<T>(_ items: [T]) async {
// Compiler error if T is not Sendable
await doSomethingWith(items)
}

// Solution: Add Sendable constraint
func process<T: Sendable>(_ items: [T]) async {
await doSomethingWith(items)
}









Decision Framework



When working with Sendable, use this decision framework:





  1. Is it a value type (struct/enum)?




    • Ensure all properties are Sendable

    • Prefer immutable properties

    • Consider functional update patterns




  2. Is it a reference type (class)?




    • Can it be made immutable? → Make it immutable

    • Does it need mutation? → Consider using an actor instead

    • Must it be a class? → Add proper synchronization




  3. Does it cross concurrency boundaries?




    • Yes → Must be Sendable

    • No → Sendable not required (but still beneficial)




  4. Are there compiler warnings?




    • Address them immediately

    • Don't suppress with @unchecked unless absolutely necessary

    • Consider architectural changes








Performance Considerations



Sendable types can impact performance in various ways:






Value Type Copying






// Large structs may have copying overhead
struct LargeDataSet: Sendable {
let values: [Double] // Could be thousands of elements
}

// Consider using reference types with proper synchronization for large data
actor LargeDataManager {
private let values: [Double]

init(values: [Double]) {
self.values = values
}

func getValue(at index: Int) -> Double? {
guard index < values.count else { return nil }
return values[index]
}
}









Synchronization Overhead






// Fine for occasional access
final class SynchronizedCounter: Sendable {
private let lock = NSLock()
private var _value: Int = 0

var value: Int {
lock.withLock { _value }
}
}

// Better for frequent access
actor CounterActor {
private var value: Int = 0

func getValue() -> Int {
return value
}

func increment() {
value += 1
}
}









Advanced Patterns






Sendable Wrappers






// Wrapper for non-Sendable types
struct SendableWrapper<T>: Sendable where T: Sendable {
let value: T

init(_ value: T) {
self.value = value
}
}

// Atomic wrapper for simple values
@propertyWrapper
struct Atomic<T: Sendable>: Sendable {
private let lock = NSLock()
private var _value: T

init(wrappedValue: T) {
_value = wrappedValue
}

var wrappedValue: T {
get {
lock.withLock { _value }
}
set {
lock.withLock { _value = newValue }
}
}
}

// Usage
actor SettingsManager {
@Atomic private var isDarkMode: Bool = false
@Atomic private var notificationsEnabled: Bool = true

func toggleDarkMode() {
isDarkMode.toggle()
}
}









Protocol Extensions for Sendable






protocol SendableIdentifiable: Sendable, Identifiable where ID: Sendable {}

extension SendableIdentifiable {
func isSame(as other: Self) -> Bool {
return self.id == other.id
}
}

// Usage
struct Product: SendableIdentifiable {
let id: UUID
let name: String
let price: Double
}






Understanding Sendable is essential for building robust, concurrent iOS applications. The protocol serves as a compiler-enforced safety net that prevents data races and ensures thread-safe data sharing. While it may seem complex initially, the patterns and principles outlined here provide a solid foundation for working confidently with Swift's concurrency features.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Swift Sendable: Mastering Thread Safety in iOS Development

Thematisch verwandte Begriffe: Swift, Sendable, Mastering, Thread · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-49449 | Joplin is an open source note-taking and to-do application that organise…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick