Sendable — qué es, protocolo de seguridad de hilos

Autor: IT Sectr Publicado: 2026-06-18 Tiempo de lectura: 10 min

Sendable es un protocolo de Swift que marca los tipos seguros para transferir entre hilos. Al trabajar con concurrencia (actor, async/await, Task), el compilador de Swift requiere que todos los datos transferidos entre contextos aislados cumplan con Sendable. Esto evita la transferencia accidental de tipos no seguros que podrían provocar condiciones de carrera. El protocolo actúa como un contrato: un tipo que cumple con Sendable garantiza la ausencia de estado interno no sincronizado. Según WWDC 2021, el protocolo Sendable es un elemento obligatorio al diseñar una arquitectura segura multiproceso.

Puntos clave

  • Sendable — un protocolo que garantiza la ausencia de condiciones de carrera al transferir entre hilos
  • Tipos valor (struct, enum) cumplen automáticamente con Sendable si todas sus propiedades son Sendable
  • @unchecked Sendable — un mecanismo de omisión para clases cuya seguridad el desarrollador asume
  • Clausuras Sendable se marcan con el atributo @Sendable, que verifica la captura de variables
  • El compilador da un error si un tipo no Sendable se transfiere entre contextos aislados

¿Qué es el protocolo Sendable en Swift?

Sendable es un protocolo de la biblioteca estándar de Swift (SE-0302) que marca los tipos seguros para transferir entre dominios de aislamiento. Un dominio de aislamiento puede ser un actor, una tarea Task o un contexto @MainActor. Sendable no contiene requisitos — actúa como un marcador de seguridad.

¿Por qué se necesita Sendable?

Antes de Swift 5.5, los desarrolladores podían transferir cualquier objeto entre hilos a través de DispatchQueue, y el compilador no verificaba si era seguro. Sendable cierra esta brecha: ahora el compilador rastrea las transferencias entre hilos y bloquea las no seguras. Esto hace que el código concurrente sea más fiable incluso antes de ejecutarse.

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

class NonSendableClass {
    var counter: Int = 0
}

En el ejemplo, UserProfile puede transferirse de forma segura entre hilos porque es una estructura con propiedades constantes de tipos Sendable. NonSendableClass provocará un error de compilación al intentar transferirlo mediante await o a un Task.

Qué tipos cumplen con Sendable por defecto

Los tipos Sendable en Swift se dividen en tres categorías: tipos valor con propiedades Sendable, clases finales con estado inmutable y funciones/clausuras marcadas con @Sendable. El compilador infiere automáticamente la conformidad con Sendable para los tipos valor.

Tipos valor y conformidad automática

Struct, enum y tupla se vuelven automáticamente Sendable si todas sus propiedades y valores asociados también son Sendable. Este es un enfoque conservador: si al menos una propiedad no cumple con Sendable, todo el tipo no se reconocerá como seguro.

TipoSendableCondición
StructSí (sin declaración explícita)Todas las propiedades son Sendable
EnumSí (sin declaración explícita)Todos los valores asociados son Sendable
Final classSí (con declaración explícita)Todas las propiedades let son Sendable, sin var
Non-final classNoNo puede ser Sendable debido a herencia

Tipos básicos

Todos los tipos incorporados de Swift — Int, String, Double, Bool, Optional, Array, Dictionary, Set — cumplen con Sendable. Esto hace que la composición de tipos sea segura por defecto. El desarrollador solo debe vigilar las clases personalizadas.

Sendable y clases: @unchecked Sendable

@unchecked Sendable es un mecanismo que permite a una clase declararse explícitamente como Sendable, omitiendo las verificaciones del compilador. El desarrollador asume la responsabilidad de la seguridad de hilos de dicha clase. Esto es útil para puentes con Objective-C y estructuras optimizadas.

Cuándo usar @unchecked Sendable

@unchecked Sendable se usa cuando una clase garantiza internamente la seguridad mediante bloqueos u operaciones atómicas, pero el compilador no puede verificarlo estáticamente. Por ejemplo, una clase con os_unfair_lock o pthread_mutex_t — su seguridad de hilos está garantizada por el código, pero Swift no lo detecta.

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

Usar @unchecked Sendable debe hacerse con cuidado. Es una señal explícita para otros desarrolladores: «lo verifiqué, esto es seguro». Un error en la implementación puede provocar condiciones de carrera difíciles de detectar. Antes de usar @unchecked, asegúrate de que el tipo realmente no pueda reescribirse como un tipo valor.

Sendable en combinación con Actor

Actor y Sendable son dos caras de la misma moneda. Actor aísla su estado, pero para intercambiar datos con el mundo exterior debe devolver tipos Sendable. Si un método de actor devuelve un tipo no Sendable, el compilador emite una advertencia o error.

Transferencia de datos mediante Sendable

Cuando un actor envía datos a código externo, estos datos cruzan el límite de aislamiento. Sendable garantiza que el destinatario pueda usarlos de forma segura fuera del actor. El actor permanece aislado — su estado interno no se expone.

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 es una estructura Sendable que contiene solo propiedades let de tipos Sendable. Este enfoque es una buena práctica para extraer datos de un actor. La instantánea del estado se transfiere por valor y el actor no pierde el control sobre su estado.

Funciones y clausuras Sendable

@Sendable es un atributo para funciones y clausuras que garantiza que la clausura no captura datos no Sendable de forma mutable. Cuando una clausura se transfiere a un Task o método de actor, debe ser Sendable.

Verificación de captura en clausuras @Sendable

El compilador verifica que la clausura @Sendable no capture referencias mutables a clases. Se permite capturar propiedades let de tipos Sendable. Capturar una variable var de un tipo referencia provocará un error porque la clausura podría ejecutarse simultáneamente con la mutación.

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

let constant = "Safe"
var counter = 0
// counter — capturar var muta counter, error de compilación
performAsync { // ❌ Mutación de variable capturada
    print(constant)
}

La regla es simple: una clausura @Sendable solo puede capturar datos que sean Sendable y que no serán mutados desde fuera. Para clases, se permite capturar una referencia débil weak self si la clase no está marcada como Sendable. Esto evita ciclos de retención clásicos y condiciones de carrera.

Preguntas frecuentes

¿Qué es Sendable en Swift en palabras sencillas?

Sendable es un marcador que le dice al compilador: «este tipo se puede transferir de forma segura entre hilos». Las estructuras y constantes suelen ser Sendable por defecto, las clases no, a menos que se indique explícitamente.

¿Qué tipos cumplen automáticamente con Sendable?

Los tipos valor (struct, enum) con propiedades Sendable, las clases finales con estado inmutable y todos los tipos básicos de Swift: Int, String, Double, Bool, Array, Dictionary, Optional — cumplen con Sendable automáticamente.

¿Qué es @unchecked Sendable?

@unchecked Sendable es una forma de declarar una clase como Sendable sin verificaciones estáticas del compilador. El desarrollador garantiza la seguridad por su cuenta, a menudo mediante bloqueos u operaciones atómicas.

¿Por qué se necesita Sendable para Actor?

Actor aísla su estado, pero al devolver datos al código externo, estos datos cruzan el límite de aislamiento. Sendable garantiza que el destinatario no se encuentre con condiciones de carrera al usar estos datos fuera del actor.

¿Cómo hacer que una clase sea Sendable en Swift?

Añade el protocolo Sendable a una clase final, cuyas propiedades sean todas constantes de tipos Sendable. Si la clase usa bloqueos, se puede usar @unchecked Sendable, pero esto requiere precaución.

Resumen

  • Sendable — un protocolo marcador para transferencia segura de datos entre hilos
  • Tipos valor cumplen automáticamente con Sendable cuando se cumplen las condiciones
  • Clases requieren declaración explícita de Sendable o @unchecked Sendable
  • Actor devuelve datos al código externo solo mediante tipos Sendable
  • @Sendable atributo de clausura verifica la corrección de la captura de variables
  • El compilador verifica estáticamente la conformidad con Sendable, evitando condiciones de carrera en tiempo de compilación

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también