Sendable — ce este, protocol de siguranță a firelor

Autor: IT Sectr Publicat: 2026-06-18 Timp de citire: 10 min

Sendable — este un protocol Swift care marchează tipurile sigure pentru transmiterea între fire. În lucrul cu concurența (actor, async/await, Task), compilatorul Swift cere ca toate datele transmise între contextele izolate să fie conforme cu Sendable. Aceasta exclude transmiterea accidentală a tipurilor nesigure care pot duce la condiții de cursă. Protocolul acționează ca un contract: un tip conform cu Sendable garantează absența stării interne nesincronizate. Potrivit WWDC 2021, protocolul Sendable este un element obligatoriu în proiectarea arhitecturii sigure multi-thread.

Principalele

  • Sendable — protocol care garantează absența condițiilor de cursă la transmiterea între fire
  • Tipurile valoare (struct, enum) sunt automat conforme cu Sendable dacă toate proprietățile lor sunt Sendable
  • @unchecked Sendable — mecanism de ocolire pentru clasele a căror siguranță dezvoltatorul și-o asumă
  • Closure-urile Sendable sunt marcate cu atributul @Sendable care verifică capturarea variabilelor
  • Compilatorul emite eroare dacă un tip non-Sendable este transmis între contextele izolate

Ce este protocolul Sendable în Swift?

Sendable — este un protocol din biblioteca standard Swift (SE-0302) care marchează tipurile sigure pentru transmiterea între domenii de izolare. Prin domeniu de izolare se înțelege un actor, o sarcină Task sau un context @MainActor. Sendable nu conține cerințe — acționează ca un marker de siguranță.

De ce este necesar Sendable

Înainte de Swift 5.5, dezvoltatorii puteau transmite orice obiect între fire prin DispatchQueue, iar compilatorul nu verifica dacă este sigur. Sendable închide această breșă: acum compilatorul însuși urmărește transmiterile între fire și blochează pe cele nesigure. Acest lucru face codul concurent mai fiabil chiar înainte de execuție.

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

class NonSendableClass {
    var counter: Int = 0
}

În exemplu, UserProfile poate fi transmis între fire în siguranță, deoarece este o structură cu proprietăți constante de tipuri Sendable. NonSendableClass va cauza o eroare de compilare la încercarea de transmitere prin await sau în Task.

Ce tipuri sunt conforme implicit cu Sendable

Tipurile Sendable în Swift se împart în trei categorii: tipuri valoare cu proprietăți Sendable, clase finale cu stare imutabilă și funcții/closure-uri marcate cu @Sendable. Compilatorul deduce automat conformitatea Sendable pentru tipurile valoare.

Tipurile valoare și conformitatea automată

Struct, enum și tuple devin automat Sendable dacă toate proprietățile și valorile asociate sunt de asemenea Sendable. Aceasta este o abordare conservatoare: dacă măcar o proprietate nu este conformă cu Sendable, întregul tip nu va fi considerat sigur.

TipSendableCondiție
StructDa (fără indicare explicită)Toate proprietățile Sendable
EnumDa (fără indicare explicită)Toate valorile asociate Sendable
Final classDa (cu indicare explicită)Toate proprietățile let Sendable, fără var
Non-final classNuNu poate fi Sendable din cauza moștenirii

Tipurile de bază

Toate tipurile încorporate Swift — Int, String, Double, Bool, Optional, Array, Dictionary, Set — sunt conforme cu Sendable. Aceasta face compoziția tipurilor sigură implicit. Dezvoltatorul trebuie să fie atent doar la clasele personalizate.

Sendable și clasele: @unchecked Sendable

@unchecked Sendable — este un mecanism care permite unei clase să se declare explicit ca Sendable, ocolind verificările compilatorului. Dezvoltatorul își asumă responsabilitatea pentru siguranța firelor unei astfel de clase. Este util pentru punțile Objective-C și structurile optimizate.

Când să folosiți @unchecked Sendable

@unchecked Sendable se aplică atunci când clasa garantează intern siguranța prin blocaje sau operații atomice, dar compilatorul nu poate verifica acest lucru static. De exemplu, o clasă cu os_unfair_lock sau pthread_mutex_t — siguranța firelor este asigurată prin cod, dar Swift nu vede acest lucru.

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

Utilizați @unchecked Sendable cu prudență. Acesta este un semnal clar pentru alți dezvoltatori: „am verificat, este sigur”. O eroare în implementare poate duce la condiții de cursă greu de depistat. Înainte de a aplica @unchecked, asigurați-vă că tipul nu poate fi rescris ca tip valoare.

Sendable în combinație cu Actor

Actor și Sendable sunt două fețe ale aceleiași medalii. Actor își izolează starea, dar pentru schimbul de date cu lumea exterioară trebuie să returneze tipuri Sendable. Dacă o metodă actor returnează un tip non-Sendable, compilatorul emite un avertisment sau o eroare.

Transmiterea datelor prin Sendable

Când actor trimite date codului extern, aceste date traversează granița de izolare. Sendable garantează că destinatarul le poate folosi în siguranță în afara actorului. Actorul însuși rămâne izolat — starea sa internă nu este dezvăluită.

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 — este o structură Sendable care conține doar proprietăți let de tipuri Sendable. Această abordare este best practice pentru extragerea datelor dintr-un actor. Instantaneul stării este transmis prin valoare, iar actorul nu pierde controlul asupra stării sale.

Funcții și closure-uri Sendable

@Sendable — este un atribut pentru funcții și closure-uri care garantează că closure-ul nu capturează date non-Sendable în mod mutabil. Când un closure este transmis în Task sau unei metode actor, acesta trebuie să fie Sendable.

Verificarea capturării în closure-urile @Sendable

Compilatorul verifică dacă closure-ul @Sendable nu capturează referințe mutabile la clase. Capturarea proprietăților let ale tipurilor Sendable este permisă. Capturarea unei variabile var de tip referință va cauza o eroare, deoarece closure-ul poate fi executat simultan cu mutația.

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

let constant = "Safe"
var counter = 0
// counter — capturarea var mută contorul, eroare de compilare
performAsync { // ❌ Mutația var-ului capturat
    print(constant)
}

Regula este simplă: un closure @Sendable poate captura doar acele date care sunt ele însele Sendable și nu vor fi mutate din exterior. Pentru clase, este permisă capturarea referinței slabe weak self dacă clasa nu este marcată ca Sendable. Aceasta previne ciclurile de retain și condițiile de cursă clasice.

Întrebări frecvente

Ce este Sendable în Swift în cuvinte simple?

Sendable — este un marker care spune compilatorului: „acest tip poate fi transmis în siguranță între fire”. Structurile și constantele sunt de obicei Sendable implicit, clasele — nu, cu excepția cazului în care este specificat explicit.

Ce tipuri sunt automat conforme cu Sendable?

Tipurile valoare (struct, enum) cu proprietăți Sendable, clasele finale cu stare imutabilă, precum și toate tipurile de bază Swift: Int, String, Double, Bool, Array, Dictionary, Optional — sunt automat conforme cu Sendable.

Ce este @unchecked Sendable?

@unchecked Sendable — este o modalitate de a declara o clasă ca Sendable fără verificarea statică a compilatorului. Dezvoltatorul garantează siguranța independent, adesea prin blocaje sau operații atomice.

De ce este necesar Sendable pentru Actor?

Actorul își izolează starea, dar la returnarea datelor către codul extern, aceste date traversează granița de izolare. Sendable garantează că destinatarul nu se va confrunta cu condiții de cursă la utilizarea acestor date în afara actorului.

Cum se face o clasă Sendable în Swift?

Adăugați protocolul Sendable la o clasă finală ale cărei proprietăți sunt toate constante de tipuri Sendable. Dacă clasa utilizează blocaje, se poate aplica @unchecked Sendable, dar aceasta necesită prudență.

Rezumat

  • Sendable — protocol-marker pentru transmiterea sigură a datelor între fire
  • Tipurile valoare sunt automat conforme cu Sendable la îndeplinirea condițiilor
  • Clasele necesită indicarea explicită a Sendable sau @unchecked Sendable
  • Actor returnează date codului extern doar prin tipuri Sendable
  • @Sendable atributul closure-urilor verifică corectitudinea capturării variabilelor
  • Compilatorul verifică static conformitatea cu Sendable, prevenind condițiile de cursă în faza de compilare

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și