Sendable — was es ist, Threadsicherheitsprotokoll

Autor: IT Sectr Veröffentlicht: 2026-06-18 Lesezeit: 10 Min.

Sendable ist ein Swift-Protokoll, das Typen als sicher für die Übergabe zwischen Threads markiert. Bei der Arbeit mit Nebenläufigkeit (actor, async/await, Task) verlangt der Swift-Compiler, dass alle zwischen isolierten Kontexten übergebenen Daten Sendable entsprechen. Dies verhindert die versehentliche Übergabe unsicherer Typen, die zu Datenkonflikten führen können. Das Protokoll fungiert als Vertrag: Ein Typ, der Sendable entspricht, garantiert das Fehlen eines internen nicht synchronisierten Zustands. Laut WWDC 2021 ist das Sendable-Protokoll ein obligatorisches Element beim Entwurf einer sicheren Multithread-Architektur.

Wichtige Erkenntnisse

  • Sendable — ein Protokoll, das Datenkonflikte bei der Übergabe zwischen Threads ausschließt
  • Wertetypen (struct, enum) entsprechen automatisch Sendable, wenn alle ihre Eigenschaften Sendable sind
  • @unchecked Sendable — ein Umgehungsmechanismus für Klassen, deren Sicherheit der Entwickler selbst übernimmt
  • Sendable-Closures werden mit dem @Sendable-Attribut markiert, das die Erfassung von Variablen prüft
  • Der Compiler gibt einen Fehler aus, wenn ein nicht-Sendable-Typ zwischen isolierten Kontexten übergeben wird

Was ist das Sendable-Protokoll in Swift?

Sendable ist ein Protokoll der Swift-Standardbibliothek (SE-0302), das Typen als sicher für die Übergabe zwischen Isolationsdomänen markiert. Eine Isolationsdomäne bedeutet einen Actor, eine Task oder einen @MainActor-Kontext. Sendable enthält keine Anforderungen — es fungiert als Sicherheitsmarker.

Warum Sendable benötigt wird

Vor Swift 5.5 konnten Entwickler jedes Objekt über DispatchQueue zwischen Threads übergeben, und der Compiler prüfte nicht, ob dies sicher war. Sendable schließt diese Lücke: Jetzt verfolgt der Compiler selbst Thread-übergreifende Übergaben und blockiert unsichere. Dies macht nebenläufigen Code bereits vor der Ausführung zuverlässiger.

swift
struct UserProfile: Sendable {
    let name: String
    let age: Int
}

class NonSendableClass {
    var counter: Int = 0
}

Im Beispiel kann UserProfile sicher zwischen Threads übergeben werden, da es eine Struktur mit konstanten Eigenschaften von Sendable-Typen ist. NonSendableClass verursacht einen Kompilierungsfehler beim Versuch, es über await oder an eine Task zu übergeben.

Welche Typen entsprechen standardmäßig Sendable

Sendable-Typen in Swift fallen in drei Kategorien: Wertetypen mit Sendable-Eigenschaften, finale Klassen mit unveränderlichem Zustand und mit @Sendable markierte Funktionen/Closures. Der Compiler leitet die Sendable-Konformität für Wertetypen automatisch ab.

Wertetypen und automatische Konformität

Struct, Enum und Tuple werden automatisch Sendable, wenn alle ihre Eigenschaften und assoziierten Werte ebenfalls Sendable sind. Dies ist ein konservativer Ansatz: Wenn mindestens eine Eigenschaft nicht Sendable entspricht, wird der gesamte Typ nicht als sicher erkannt.

TypSendableBedingung
StructJa (ohne explizite Deklaration)Alle Eigenschaften sind Sendable
EnumJa (ohne explizite Deklaration)Alle assoziierten Werte sind Sendable
Final classJa (mit expliziter Deklaration)Alle let-Eigenschaften sind Sendable, kein var
Non-final classNeinKann aufgrund von Vererbung nicht Sendable sein

Basistypen

Alle integrierten Swift-Typen — Int, String, Double, Bool, Optional, Array, Dictionary, Set — entsprechen Sendable. Dies macht die Typkomposition standardmäßig sicher. Der Entwickler muss nur auf benutzerdefinierte Klassen achten.

Sendable und Klassen: @unchecked Sendable

@unchecked Sendable ist ein Mechanismus, der es einer Klasse erlaubt, sich selbst explizit als Sendable zu deklarieren und dabei Compiler-Prüfungen zu umgehen. Der Entwickler übernimmt die Verantwortung für die Threadsicherheit einer solchen Klasse. Dies ist nützlich für Objective-C-Brücken und optimierte Strukturen.

Wann @unchecked Sendable verwendet wird

@unchecked Sendable wird verwendet, wenn eine Klasse intern durch Sperren oder atomare Operationen Sicherheit gewährleistet, der Compiler dies jedoch nicht statisch überprüfen kann. Zum Beispiel eine Klasse mit os_unfair_lock oder pthread_mutex_t — ihre Threadsicherheit wird durch Code sichergestellt, aber Swift sieht dies nicht.

swift
final class AtomicCounter: @unchecked Sendable {
    private var value: Int = 0
    private let lock = NSLock()
    
    func increment() {
        lock.lock()
        value += 1
        lock.unlock()
    }
}

Die Verwendung von @unchecked Sendable sollte vorsichtig erfolgen. Es ist ein explizites Signal an andere Entwickler: „Ich habe es überprüft, es ist sicher.“ Ein Implementierungsfehler kann zu schwer auffindbaren Wettlaufsituationen führen. Bevor Sie @unchecked verwenden, stellen Sie sicher, dass der Typ wirklich nicht als Wertetyp umgeschrieben werden kann.

Sendable in Kombination mit Actor

Actor und Sendable sind zwei Seiten derselben Medaille. Actor isoliert seinen Zustand, muss aber für den Datenaustausch mit der Außenwelt Sendable-Typen zurückgeben. Wenn eine Actor-Methode einen nicht-Sendable-Typ zurückgibt, gibt der Compiler eine Warnung oder einen Fehler aus.

Datenübergabe durch Sendable

Wenn ein Actor Daten an externen Code sendet, überschreiten diese Daten die Isolationsgrenze. Sendable garantiert, dass der Empfänger sie außerhalb des Actors sicher verwenden kann. Der Actor bleibt isoliert — sein interner Zustand wird nicht offengelegt.

swift
struct AccountSnapshot: Sendable {
    let id: UUID
    let balance: Double
    let lastUpdated: Date
}

actor BankActor {
    private var balance: Double = 0
    
    func snapshot() async -> AccountSnapshot {
        return AccountSnapshot(
            id: UUID(),
            balance: balance,
            lastUpdated: Date()
        )
    }
}

AccountSnapshot ist eine Sendable-Struktur, die nur let-Eigenschaften von Sendable-Typen enthält. Dieser Ansatz ist eine bewährte Methode zum Extrahieren von Daten aus einem Actor. Der Zustandssnapshot wird als Wert übergeben, und der Actor verliert nicht die Kontrolle über seinen Zustand.

Sendable-Funktionen und -Closures

@Sendable ist ein Attribut für Funktionen und Closures, das garantiert, dass die Closure keine nicht-Sendable-Daten auf veränderliche Weise erfasst. Wenn eine Closure an eine Task oder Actor-Methode übergeben wird, muss sie Sendable sein.

Erfassungsprüfung in @Sendable-Closures

Der Compiler prüft, dass die @Sendable-Closure keine veränderlichen Referenzen auf Klassen erfasst. Das Erfassen von let-Eigenschaften von Sendable-Typen ist erlaubt. Das Erfassen einer var-Variable eines Referenztyps führt zu einem Fehler, da die Closure gleichzeitig mit der Mutation ausgeführt werden könnte.

swift
func performAsync(operation: @Sendable () -> Void) {
    Task {
        await operation()
    }
}

let constant = "Safe"
var counter = 0
// counter — Erfassen von var mutiert counter, Kompilierungsfehler
performAsync { // ❌ Mutation der erfassten Variable
    print(constant)
}

Die Regel ist einfach: Eine @Sendable-Closure kann nur Daten erfassen, die selbst Sendable sind und von außen nicht mutiert werden. Bei Klassen ist das Erfassen einer schwachen Referenz weak self erlaubt, wenn die Klasse nicht als Sendable markiert ist. Dies verhindert klassische retain-Zyklen und Wettlaufsituationen.

Häufig gestellte Fragen

Was ist Sendable in Swift in einfachen Worten?

Sendable ist ein Marker, der dem Compiler sagt: „Dieser Typ kann sicher zwischen Threads übergeben werden.“ Strukturen und Konstanten sind normalerweise standardmäßig Sendable, Klassen nicht, sofern nicht explizit angegeben.

Welche Typen entsprechen automatisch Sendable?

Wertetypen (struct, enum) mit Sendable-Eigenschaften, finale Klassen mit unveränderlichem Zustand und alle grundlegenden Swift-Typen: Int, String, Double, Bool, Array, Dictionary, Optional — entsprechen automatisch Sendable.

Was ist @unchecked Sendable?

@unchecked Sendable ist eine Möglichkeit, eine Klasse ohne statische Compiler-Prüfung als Sendable zu deklarieren. Der Entwickler garantiert die Sicherheit selbst, oft durch Sperren oder atomare Operationen.

Warum wird Sendable für Actor benötigt?

Actor isoliert seinen Zustand, aber bei der Rückgabe von Daten an externen Code überschreiten diese Daten die Isolationsgrenze. Sendable garantiert, dass der Empfänger bei der Verwendung dieser Daten außerhalb des Actors nicht auf Wettlaufsituationen stößt.

Wie macht man eine Klasse in Swift Sendable?

Fügen Sie das Sendable-Protokoll zu einer finalen Klasse hinzu, deren Eigenschaften allesamt Konstanten von Sendable-Typen sind. Wenn die Klasse Sperren verwendet, kann @unchecked Sendable verwendet werden, aber das erfordert Vorsicht.

Zusammenfassung

  • Sendable — ein Marker-Protokoll für sichere threadübergreifende Datenübergabe
  • Wertetypen entsprechen automatisch Sendable, wenn die Bedingungen erfüllt sind
  • Klassen erfordern eine explizite Sendable- oder @unchecked Sendable-Deklaration
  • Actor gibt Daten nur über Sendable-Typen an externen Code zurück
  • @Sendable Closure-Attribut prüft die Korrektheit der Variablenerfassung
  • Der Compiler prüft statisch die Sendable-Konformität und verhindert Wettlaufsituationen zur Build-Zeit

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch