Sendable — co to je, protokol bezpečnosti vláken

Autor: IT Sectr Publikováno: 2026-06-18 Doba čtení: 10 min

Sendable — je Swift protokol, který označuje typy bezpečné pro přenos mezi vlákny. Při práci s konkurencí (actor, async/await, Task) Swift kompilátor vyžaduje, aby všechna data přenášená mezi izolovanými kontexty byla v souladu se Sendable. To vylučuje náhodný přenos nebezpečných typů, které mohou vést k datovým závodům. Protokol funguje jako smlouva: typ, který je v souladu se Sendable, zaručuje absenci vnitřního nesynchronizovaného stavu. Podle WWDC 2021 je protokol Sendable povinným prvkem při navrhování bezpečné vícevláknové architektury.

Hlavní

  • Sendable — protokol zaručující absenci datových závodů při přenosu mezi vlákny
  • Hodnotové typy (struct, enum) automaticky splňují Sendable, pokud všechny jejich vlastnosti jsou Sendable
  • @unchecked Sendable — obcházecí mechanismus pro třídy, jejichž bezpečnost přebírá vývojář na sebe
  • Sendable uzávěry jsou označeny atributem @Sendable, který kontroluje záchyt proměnných
  • Kompilátor vydá chybu, pokud je ne-Sendable typ přenášen mezi izolovanými kontexty

Co je protokol Sendable v Swift?

Sendable — je protokol ze standardní knihovny Swift (SE-0302), který označuje typy bezpečné pro přenos mezi doménami izolace. Doménou izolace se rozumí actor, úloha Task nebo kontext @MainActor. Sendable neobsahuje požadavky — funguje jako bezpečnostní značka.

Proč je Sendable potřeba

Před Swift 5.5 mohli vývojáři přenášet libovolný objekt mezi vlákny přes DispatchQueue a kompilátor nekontroloval, zda je to bezpečné. Sendable uzavírá tuto mezeru: nyní kompilátor sám sleduje mezipřenosy mezi vlákny a blokuje nebezpečné. To činí souběžný kód spolehlivějším ještě před spuštěním.

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

class NonSendableClass {
    var counter: Int = 0
}

V příkladu může být UserProfile bezpečně přenesen mezi vlákny, protože se jedná o strukturu s konstantními vlastnostmi Sendable typů. NonSendableClass způsobí chybu kompilace při pokusu o přenos přes await nebo do Task.

Které typy implicitně splňují Sendable

Sendable typy v Swift se dělí do tří kategorií: hodnotové typy s vlastnostmi Sendable, finální třídy s neměnným stavem a funkce/uzávěry označené @Sendable. Kompilátor automaticky odvozuje soulad se Sendable pro hodnotové typy.

Hodnotové typy a automatický soulad

Struct, enum a tuple se automaticky stávají Sendable, pokud všechny jejich vlastnosti a přidružené hodnoty jsou také Sendable. Toto je konzervativní přístup: pokud alespoň jedna vlastnost není v souladu se Sendable, celý typ nebude považován za bezpečný.

TypSendablePodmínka
StructAno (bez explicitního uvedení)Všechny vlastnosti Sendable
EnumAno (bez explicitního uvedení)Všechny přidružené hodnoty Sendable
Final classAno (s explicitním uvedením)Všechny let vlastnosti Sendable, žádné var
Non-final classNeNemůže být Sendable kvůli dědičnosti

Základní typy

Všechny vestavěné Swift typy — Int, String, Double, Bool, Optional, Array, Dictionary, Set — jsou v souladu se Sendable. To činí kompozici typů implicitně bezpečnou. Vývojář se musí starat pouze o vlastní třídy.

Sendable a třídy: @unchecked Sendable

@unchecked Sendable — je mechanismus umožňující třídě explicitně se prohlásit za Sendable, obcházející kontroly kompilátoru. Vývojář přebírá odpovědnost za bezpečnost vláken takové třídy. To je užitečné pro mosty Objective-C a optimalizované struktury.

Kdy používat @unchecked Sendable

@unchecked Sendable se aplikuje, když třída interně zaručuje bezpečnost prostřednictvím zámků nebo atomických operací, ale kompilátor to nemůže staticky zkontrolovat. Například třída s os_unfair_lock nebo pthread_mutex_t — její bezpečnost vláken je zajištěna kódem, ale Swift to nevidí.

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

@unchecked Sendable používejte opatrně. Toto je jasný signál pro ostatní vývojáře: „Zkontroloval jsem, je to bezpečné”. Chyba v implementaci může vést k obtížně odhalitelným závodům. Před použitím @unchecked se ujistěte, že typ opravdu nelze přepsat jako hodnotový typ.

Sendable v kombinaci s Actor

Actor a Sendable jsou dvě strany téže mince. Actor izoluje svůj stav, ale pro výměnu dat s vnějším světem musí vracet Sendable typy. Pokud metoda actor vrací ne-Sendable typ, kompilátor vydá varování nebo chybu.

Přenos dat prostřednictvím Sendable

Když actor posílá data externímu kódu, tato data překračují hranici izolace. Sendable zaručuje, že příjemce může bezpečně používat mimo actor. Samotný actor zůstává izolovaný — jeho vnitřní stav není odhalen.

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 — je Sendable struktura, která obsahuje pouze let vlastnosti Sendable typů. Tento přístup je best practice pro extrakci dat z actor. Snímek stavu je přenášen hodnotou a actor neztrácí kontrolu nad svým stavem.

Sendable funkce a uzávěry

@Sendable — je atribut pro funkce a uzávěry, který zaručuje, že uzávěr nezachycuje ne-Sendable data měnitelným způsobem. Když je uzávěr předán do Task nebo metody actor, musí být Sendable.

Kontrola záchytu v @Sendable uzávěrech

Kompilátor kontroluje, že @Sendable uzávěr nezachycuje měnítelné reference na třídy. Zachycení let vlastností Sendable typů je povoleno. Zachycení var proměnné referenčního typu způsobí chybu, protože uzávěr může být proveden současně s mutací.

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

let constant = "Safe"
var counter = 0
// counter — zachycení var mutuje počítadlo, chyba kompilace
performAsync { // ❌ Mutace zachyceného var
    print(constant)
}

Pravidlo je jednoduché: @Sendable uzávěr může zachytit pouze ta data, která jsou sama Sendable a nebudou mutována zvenčí. Pro třídy je povoleno zachycení slabé reference weak self, pokud třída není označena jako Sendable. To zabraňuje klasickým retain cycle a race condition.

Často kladené otázky

Co je Sendable v Swift jednoduchými slovy?

Sendable — je značka, která říká kompilátoru: „Tento typ lze bezpečně přenášet mezi vlákny”. Struktury a konstanty jsou obvykle implicitně Sendable, třídy — ne, pokud to není výslovně uvedeno.

Které typy automaticky splňují Sendable?

Hodnotové typy (struct, enum) s vlastnostmi Sendable, finální třídy s neměnným stavem, stejně jako všechny základní Swift typy: Int, String, Double, Bool, Array, Dictionary, Optional — automaticky splňují Sendable.

Co je @unchecked Sendable?

@unchecked Sendable — je způsob, jak prohlásit třídu za Sendable bez statické kontroly kompilátorem. Vývojář zaručuje bezpečnost samostatně, často prostřednictvím zámků nebo atomických operací.

Proč je Sendable potřeba pro Actor?

Actor izoluje svůj stav, ale při vracení dat externímu kódu tato data překračují hranici izolace. Sendable zaručuje, že příjemce nenarazí na závody při používání těchto dat mimo actor.

Jak udělat třídu Sendable v Swift?

Přidejte protokol Sendable k finální třídě, jejíž všechny vlastnosti jsou konstanty Sendable typů. Pokud třída používá zámky, lze aplikovat @unchecked Sendable, ale to vyžaduje opatrnost.

Shrnutí

  • Sendable — marker protokol pro bezpečný přenos dat mezi vlákny
  • Hodnotové typy automaticky splňují Sendable při splnění podmínek
  • Třídy vyžadují explicitní uvedení Sendable nebo @unchecked Sendable
  • Actor vrací data externímu kódu pouze prostřednictvím Sendable typů
  • @Sendable atribut uzávěrů kontroluje správnost zachycení proměnných
  • Kompilátor staticky kontroluje soulad se Sendable, čímž předchází závodům ve fázi sestavení

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také