Sendable — vad är det, protokoll för trådsäkerhet

Författare: IT Sectr Publicerad: 2026-06-18 Lästid: 10 min

Sendable — är ett Swift-protokoll som markerar typer som är säkra att överföra mellan trådar. Vid arbete med konkurrens (actor, async/await, Task) kräver Swift-kompilatorn att all data som överförs mellan isolerade kontexter måste följa Sendable. Detta förhindrar oavsiktlig överföring av osäkra typer som kan leda till datarace. Protokollet fungerar som ett kontrakt: en typ som följer Sendable garanterar frånvaron av internt osynkroniserat tillstånd. Enligt WWDC 2021 är Sendable-protokollet ett obligatoriskt element vid design av säker flertrådad arkitektur.

Huvudsakligt

  • Sendable — protokoll som garanterar frånvaro av datarace vid överföring mellan trådar
  • Värdetyper (struct, enum) följer automatiskt Sendable om alla deras egenskaper är Sendable
  • @unchecked Sendable — förbikopplingsmekanism för klasser vars säkerhet utvecklaren tar ansvar för
  • Sendable-slutningar markeras med attributet @Sendable som kontrollerar infångning av variabler
  • Kompilatorn ger fel om en icke-Sendable-typ överförs mellan isolerade kontexter

Vad är Sendable-protokollet i Swift?

Sendable — är ett protokoll från Swifts standardbibliotek (SE-0302) som markerar typer som är säkra att överföra mellan isoleringsdomäner. Med isoleringsdomän avses en actor, en Task-uppgift eller en @MainActor-kontext. Sendable innehåller inga krav — det fungerar som en säkerhetsmarkör.

Varför Sendable behövs

Före Swift 5.5 kunde utvecklare överföra vilket objekt som helst mellan trådar via DispatchQueue, och kompilatorn kontrollerade inte om det var säkert. Sendable täpper till detta hål: nu övervakar kompilatorn själv överföringar mellan trådar och blockerar osäkra sådana. Detta gör konkurrent kod mer tillförlitlig redan innan den körs.

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

class NonSendableClass {
    var counter: Int = 0
}

I exemplet kan UserProfile säkert överföras mellan trådar eftersom det är en struktur med konstanta egenskaper av Sendable-typer. NonSendableClass orsakar ett kompileringsfel vid försök att överföra via await eller till Task.

Vilka typer följer Sendable som standard

Sendable-typer i Swift delas in i tre kategorier: värdetyper med Sendable-egenskaper, slutgiltiga klasser med oföränderligt tillstånd och funktioner/slutningar markerade med @Sendable. Kompilatorn härleder automatiskt överensstämmelse med Sendable för värdetyper.

Värdetyper och automatisk överensstämmelse

Struct, enum och tuple blir automatiskt Sendable om alla deras egenskaper och associerade värden också är Sendable. Detta är ett konservativt tillvägagångssätt: om även en enda egenskap inte följer Sendable kommer hela typen inte att anses säker.

TypSendableVillkor
StructJa (utan explicit angivelse)Alla egenskaper Sendable
EnumJa (utan explicit angivelse)Alla associerade värden Sendable
Final classJa (med explicit angivelse)Alla let-egenskaper Sendable, inga var
Non-final classNejKan inte vara Sendable på grund av arv

Grundtyper

Alla inbyggda Swift-typer — Int, String, Double, Bool, Optional, Array, Dictionary, Set — följer Sendable. Detta gör typsammansättning som standard säker. Utvecklaren behöver bara vara uppmärksam på anpassade klasser.

Sendable och klasser: @unchecked Sendable

@unchecked Sendable — är en mekanism som gör att en klass explicit kan deklarera sig som Sendable och kringgå kompilatorns kontroller. Utvecklaren tar ansvar för trådsäkerheten för en sådan klass. Detta är användbart för Objective-C-bryggor och optimerade strukturer.

När ska @unchecked Sendable användas

@unchecked Sendable tillämpas när en klass internt garanterar säkerhet genom lås eller atomära operationer, men kompilatorn inte kan kontrollera detta statiskt. Till exempel en klass med os_unfair_lock eller pthread_mutex_t — dess trådsäkerhet säkerställs av koden, men Swift ser inte detta.

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

Använd @unchecked Sendable försiktigt. Detta är en tydlig signal till andra utvecklare: ”Jag har kontrollerat, det är säkert”. Ett fel i implementeringen kan leda till svårupptäckta race-förhållanden. Innan du tillämpar @unchecked, se till att typen verkligen inte kan skrivas om som en värdetyp.

Sendable i kombination med Actor

Actor och Sendable är två sidor av samma mynt. Actor isolerar sitt tillstånd, men för datautbyte med omvärlden måste den returnera Sendable-typer. Om en actormetod returnerar en icke-Sendable-typ, ger kompilatorn en varning eller ett fel.

Dataöverföring via Sendable

När en actor skickar data till extern kod passerar dessa data isoleringsgränsen. Sendable garanterar att mottagaren kan använda dem säkert utanför aktorn. Själva aktorn förblir isolerad — dess interna tillstånd avslöjas inte.

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 — är en Sendable-struktur som endast innehåller let-egenskaper av Sendable-typer. Detta tillvägagångssätt är best practice för att extrahera data från en actor. En ögonblicksbild av tillståndet överförs efter värde och aktorn förlorar inte kontrollen över sitt tillstånd.

Sendable-funktioner och slutningar

@Sendable — är ett attribut för funktioner och slutningar som garanterar att slutningen inte fångar icke-Sendable-data på ett muterbart sätt. När en slutning skickas till Task eller en actormetod måste den vara Sendable.

Kontroll av infångning i @Sendable-slutningar

Kompilatorn kontrollerar att @Sendable-slutningen inte fångar muterbara referenser till klasser. Infångning av let-egenskaper av Sendable-typer är tillåtet. Infångning av en var-variabel av referenstyp orsakar ett fel, eftersom slutningen kan köras samtidigt med mutation.

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

let constant = "Safe"
var counter = 0
// counter — att fånga var muterar räknaren, kompileringsfel
performAsync { // ❌ Mutation av fångad var
    print(constant)
}

Regeln är enkel: en @Sendable-slutning kan bara fånga sådan data som själv är Sendable och inte kommer att muteras utifrån. För klasser är infångning av weak self-referens tillåten om klassen inte är markerad som Sendable. Detta förhindrar klassiska retain-cykler och race-förhållanden.

Vanliga frågor

Vad är Sendable i Swift med enkla ord?

Sendable — är en markör som säger till kompilatorn: ”Den här typen kan säkert överföras mellan trådar”. Strukturer och konstanter är vanligtvis Sendable som standard, klasser — inte, om det inte anges explicit.

Vilka typer följer automatiskt Sendable?

Värdetyper (struct, enum) med Sendable-egenskaper, slutgiltiga klasser med oföränderligt tillstånd, samt alla grundläggande Swift-typer: Int, String, Double, Bool, Array, Dictionary, Optional — följer automatiskt Sendable.

Vad är @unchecked Sendable?

@unchecked Sendable — är ett sätt att deklarera en klass som Sendable utan statisk kompilatorkontroll. Utvecklaren garanterar säkerheten själv, ofta genom lås eller atomära operationer.

Varför behövs Sendable för Actor?

Actor isolerar sitt tillstånd, men när data returneras till extern kod passerar dessa data isoleringsgränsen. Sendable garanterar att mottagaren inte stöter på race-förhållanden vid användning av dessa data utanför aktorn.

Hur gör man en klass Sendable i Swift?

Lägg till protokollet Sendable till en slutgiltig klass vars alla egenskaper är konstanter av Sendable-typer. Om klassen använder lås kan @unchecked Sendable tillämpas, men detta kräver försiktighet.

Sammanfattning

  • Sendable — markeringsprotokoll för säker dataöverföring mellan trådar
  • Värdetyper följer automatiskt Sendable när villkoren är uppfyllda
  • Klasser kräver explicit angivelse av Sendable eller @unchecked Sendable
  • Actor returnerar data till extern kod endast via Sendable-typer
  • @Sendable slutningsattribut kontrollerar korrekt infångning av variabler
  • Kompilatorn kontrollerar statiskt överensstämmelse med Sendable och förhindrar race-förhållanden i byggfasen

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också