Sendable — ce que c'est, protocole de sécurité des threads

Auteur : IT Sectr Publié le : 2026-06-18 Temps de lecture : 10 min

Sendable est un protocole Swift qui marque les types comme sûrs pour le transfert entre threads. Lorsqu'on travaille avec la concurrence (actor, async/await, Task), le compilateur Swift exige que toutes les données transférées entre contextes isolés soient conformes à Sendable. Cela évite le transfert accidentel de types non sûrs qui pourraient entraîner des compétitions de données. Le protocole agit comme un contrat : un type conforme à Sendable garantit l'absence d'état interne non synchronisé. Selon WWDC 2021, le protocole Sendable est un élément obligatoire lors de la conception d'une architecture multithread sécurisée.

Points clés

  • Sendable — un protocole qui garantit l'absence de compétitions de données lors du transfert entre threads
  • Types valeur (struct, enum) sont automatiquement conformes à Sendable si toutes leurs propriétés sont Sendable
  • @unchecked Sendable — un mécanisme de contournement pour les classes dont la sécurité est assumée par le développeur
  • Closures Sendable sont marquées avec l'attribut @Sendable, qui vérifie la capture de variables
  • Le compilateur génère une erreur si un type non Sendable est transféré entre contextes isolés

Qu'est-ce que le protocole Sendable en Swift ?

Sendable est un protocole de la bibliothèque standard Swift (SE-0302) qui marque les types comme sûrs pour le transfert entre domaines d'isolation. Un domaine d'isolation désigne un actor, une tâche Task ou un contexte @MainActor. Sendable ne contient aucune exigence — il agit comme un marqueur de sécurité.

Pourquoi Sendable est nécessaire

Avant Swift 5.5, les développeurs pouvaient transférer n'importe quel objet entre threads via DispatchQueue, et le compilateur ne vérifiait pas si c'était sûr. Sendable comble cette lacune : désormais, le compilateur lui-même suit les transferts entre threads et bloque ceux qui sont dangereux. Cela rend le code concurrent plus fiable avant même son exécution.

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

class NonSendableClass {
    var counter: Int = 0
}

Dans l'exemple, UserProfile peut être transféré en toute sécurité entre threads car c'est une structure avec des propriétés constantes de types Sendable. NonSendableClass provoquera une erreur de compilation lors d'une tentative de transfert via await ou vers une Task.

Quels types sont conformes à Sendable par défaut

Les types Sendable en Swift se divisent en trois catégories : les types valeur avec propriétés Sendable, les classes finales avec état immuable et les fonctions/closures marquées @Sendable. Le compilateur déduit automatiquement la conformité Sendable pour les types valeur.

Types valeur et conformité automatique

Struct, Enum et tuple deviennent automatiquement Sendable si toutes leurs propriétés et valeurs associées sont également Sendable. C'est une approche conservatrice : si au moins une propriété n'est pas conforme à Sendable, le type entier ne sera pas reconnu comme sûr.

TypeSendableCondition
StructOui (sans déclaration explicite)Toutes les propriétés sont Sendable
EnumOui (sans déclaration explicite)Toutes les valeurs associées sont Sendable
Final classOui (avec déclaration explicite)Toutes les propriétés let sont Sendable, pas de var
Non-final classNonNe peut pas être Sendable à cause de l'héritage

Types de base

Tous les types intégrés Swift — Int, String, Double, Bool, Optional, Array, Dictionary, Set — sont conformes à Sendable. Cela rend la composition de types sûre par défaut. Le développeur n'a qu'à surveiller les classes personnalisées.

Sendable et classes : @unchecked Sendable

@unchecked Sendable est un mécanisme qui permet à une classe de se déclarer explicitement comme Sendable, en contournant les vérifications du compilateur. Le développeur assume la responsabilité de la sécurité des threads de cette classe. C'est utile pour les ponts Objective-C et les structures optimisées.

Quand utiliser @unchecked Sendable

@unchecked Sendable est utilisé lorsqu'une classe garantit internement la sécurité par des verrous ou des opérations atomiques, mais le compilateur ne peut pas le vérifier statiquement. Par exemple, une classe avec os_unfair_lock ou pthread_mutex_t — sa sécurité des threads est assurée par le code, mais Swift ne le voit pas.

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

L'utilisation de @unchecked Sendable doit être faite avec prudence. C'est un signal explicite aux autres développeurs : « J'ai vérifié, c'est sûr. » Une erreur d'implémentation peut entraîner des compétitions difficiles à détecter. Avant d'utiliser @unchecked, assurez-vous que le type ne peut vraiment pas être réécrit comme un type valeur.

Sendable en combinaison avec Actor

Actor et Sendable sont les deux faces d'une même pièce. Actor isole son état, mais pour échanger des données avec le monde extérieur, il doit retourner des types Sendable. Si une méthode d'actor retourne un type non Sendable, le compilateur émet un avertissement ou une erreur.

Transfert de données via Sendable

Lorsqu'un actor envoie des données à du code externe, ces données traversent la limite d'isolation. Sendable garantit que le destinataire peut les utiliser en toute sécurité en dehors de l'actor. L'actor reste isolé — son état interne n'est pas exposé.

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 est une structure Sendable qui contient uniquement des propriétés let de types Sendable. Cette approche est une bonne pratique pour extraire des données d'un actor. L'instantané d'état est transmis par valeur, et l'actor ne perd pas le contrôle de son état.

Fonctions et closures Sendable

@Sendable est un attribut pour les fonctions et closures qui garantit que la closure ne capture pas de données non Sendable de manière mutable. Lorsqu'une closure est transférée à une Task ou à une méthode d'actor, elle doit être Sendable.

Vérification de capture dans les closures @Sendable

Le compilateur vérifie que la closure @Sendable ne capture pas de références mutables vers des classes. La capture de propriétés let de types Sendable est autorisée. La capture d'une variable var d'un type référence entraînera une erreur car la closure pourrait être exécutée simultanément avec la mutation.

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

let constant = "Safe"
var counter = 0
// counter — capturer var mute counter, erreur de compilation
performAsync { // ❌ Mutation de la variable capturée
    print(constant)
}

La règle est simple : une closure @Sendable ne peut capturer que les données qui sont elles-mêmes Sendable et qui ne seront pas mutées de l'extérieur. Pour les classes, la capture d'une référence faible weak self est autorisée si la classe n'est pas marquée comme Sendable. Cela évite les cycles de rétention classiques et les compétitions de données.

Questions fréquentes

Qu'est-ce que Sendable en Swift en termes simples ?

Sendable est un marqueur qui indique au compilateur : « ce type peut être transféré en toute sécurité entre threads ». Les structures et constantes sont généralement Sendable par défaut, les classes ne le sont pas sauf indication explicite.

Quels types sont automatiquement conformes à Sendable ?

Les types valeur (struct, enum) avec propriétés Sendable, les classes finales avec état immuable, et tous les types de base Swift : Int, String, Double, Bool, Array, Dictionary, Optional — sont automatiquement conformes à Sendable.

Qu'est-ce que @unchecked Sendable ?

@unchecked Sendable est un moyen de déclarer une classe comme Sendable sans vérification statique du compilateur. Le développeur garantit la sécurité lui-même, souvent par des verrous ou des opérations atomiques.

Pourquoi Sendable est-il nécessaire pour Actor ?

Actor isole son état, mais lors du retour de données au code externe, ces données traversent la limite d'isolation. Sendable garantit que le destinataire ne rencontrera pas de compétitions en utilisant ces données en dehors de l'actor.

Comment rendre une classe Sendable en Swift ?

Ajoutez le protocole Sendable à une classe finale dont toutes les propriétés sont des constantes de types Sendable. Si la classe utilise des verrous, @unchecked Sendable peut être utilisé, mais cela nécessite de la prudence.

Résumé

  • Sendable — un protocole marqueur pour le transfert sécurisé de données entre threads
  • Types valeur sont automatiquement conformes à Sendable lorsque les conditions sont remplies
  • Classes nécessitent une déclaration explicite Sendable ou @unchecked Sendable
  • Actor retourne des données au code externe uniquement via des types Sendable
  • @Sendable attribut de closure vérifie la correction de la capture de variables
  • Le compilateur vérifie statiquement la conformité Sendable, empêchant les compétitions à la compilation

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi