Sendable — o que é, protocolo de segurança de threads

Autor: IT Sectr Publicado: 2026-06-18 Tempo de leitura: 10 min

Sendable é um protocolo Swift que marca tipos seguros para transferência entre threads. Ao trabalhar com concorrência (actor, async/await, Task), o compilador Swift exige que todos os dados transferidos entre contextos isolados estejam em conformidade com Sendable. Isso evita a transferência acidental de tipos inseguros que podem levar a condições de corrida. O protocolo atua como um contrato: um tipo em conformidade com Sendable garante a ausência de estado interno não sincronizado. De acordo com WWDC 2021, o protocolo Sendable é um elemento obrigatório ao projetar uma arquitetura segura multithread.

Principais conclusões

  • Sendable — um protocolo que garante ausência de condições de corrida ao transferir entre threads
  • Tipos de valor (struct, enum) estão automaticamente em conformidade com Sendable se todas as suas propriedades forem Sendable
  • @unchecked Sendable — um mecanismo de bypass para classes cuja segurança o desenvolvedor assume responsabilidade
  • Closures Sendable são marcadas com o atributo @Sendable, que verifica a captura de variáveis
  • O compilador emite erro se um tipo não Sendable for transferido entre contextos isolados

O que é o protocolo Sendable em Swift?

Sendable é um protocolo da biblioteca padrão Swift (SE-0302) que marca tipos seguros para transferência entre domínios de isolamento. Um domínio de isolamento significa um actor, uma tarefa Task ou um contexto @MainActor. Sendable não contém requisitos — atua como um marcador de segurança.

Por que o Sendable é necessário

Antes do Swift 5.5, os desenvolvedores podiam transferir qualquer objeto entre threads via DispatchQueue, e o compilador não verificava se era seguro. Sendable fecha essa lacuna: agora o compilador rastreia as transferências entre threads e bloqueia as inseguras. Isso torna o código concorrente mais confiável mesmo antes de ser executado.

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

class NonSendableClass {
    var counter: Int = 0
}

No exemplo, UserProfile pode ser transferido com segurança entre threads porque é uma struct com propriedades constantes de tipos Sendable. NonSendableClass causará um erro de compilação ao tentar transferi-lo via await ou para um Task.

Quais tipos estão em conformidade com Sendable por padrão

Os tipos Sendable em Swift dividem-se em três categorias: tipos de valor com propriedades Sendable, classes finais com estado imutável e funções/closures marcadas com @Sendable. O compilador infere automaticamente a conformidade com Sendable para tipos de valor.

Tipos de valor e conformidade automática

Struct, enum e tupla tornam-se automaticamente Sendable se todas as suas propriedades e valores associados também forem Sendable. Esta é uma abordagem conservadora: se pelo menos uma propriedade não estiver em conformidade com Sendable, o tipo inteiro não será reconhecido como seguro.

TipoSendableCondição
StructSim (sem declaração explícita)Todas as propriedades são Sendable
EnumSim (sem declaração explícita)Todos os valores associados são Sendable
Final classSim (com declaração explícita)Todas as propriedades let são Sendable, sem var
Non-final classNãoNão pode ser Sendable devido à herança

Tipos básicos

Todos os tipos incorporados do Swift — Int, String, Double, Bool, Optional, Array, Dictionary, Set — estão em conformidade com Sendable. Isso torna a composição de tipos segura por padrão. O desenvolvedor só precisa cuidar das classes personalizadas.

Sendable e classes: @unchecked Sendable

@unchecked Sendable é um mecanismo que permite a uma classe declarar-se explicitamente como Sendable, ignorando as verificações do compilador. O desenvolvedor assume a responsabilidade pela segurança de threads dessa classe. Isso é útil para pontes Objective-C e estruturas otimizadas.

Quando usar @unchecked Sendable

@unchecked Sendable é usado quando uma classe garante internamente a segurança por meio de locks ou operações atômicas, mas o compilador não pode verificar isso estaticamente. Por exemplo, uma classe com os_unfair_lock ou pthread_mutex_t — sua segurança de threads é garantida pelo código, mas o Swift não vê isso.

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 deve ser feito com cuidado. É um sinal explícito para outros desenvolvedores: «verifiquei, é seguro». Um erro na implementação pode levar a condições de corrida difíceis de encontrar. Antes de usar @unchecked, certifique-se de que o tipo realmente não pode ser reescrito como um tipo de valor.

Sendable em combinação com Actor

Actor e Sendable são dois lados da mesma moeda. Actor isola seu estado, mas para trocar dados com o mundo exterior deve retornar tipos Sendable. Se um método de actor retornar um tipo não Sendable, o compilador emite um aviso ou erro.

Transferência de dados via Sendable

Quando um actor envia dados para código externo, esses dados cruzam o limite de isolamento. Sendable garante que o destinatário possa usá-los com segurança fora do actor. O actor permanece isolado — seu estado interno não é exposto.

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 é uma struct Sendable que contém apenas propriedades let de tipos Sendable. Essa abordagem é uma boa prática para extrair dados de um actor. O snapshot do estado é transferido por valor, e o actor não perde o controle sobre seu estado.

Funções e closures Sendable

@Sendable é um atributo para funções e closures que garante que a closure não capture dados não Sendable de forma mutável. Quando uma closure é transferida para um Task ou método de actor, ela deve ser Sendable.

Verificação de captura em closures @Sendable

O compilador verifica que a closure @Sendable não captura referências mutáveis para classes. Capturar propriedades let de tipos Sendable é permitido. Capturar uma variável var de um tipo de referência causará erro porque a closure pode ser executada simultaneamente com a mutação.

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

let constant = "Safe"
var counter = 0
// counter — capturar var muta counter, erro de compilação
performAsync { // ❌ Mutação de variável capturada
    print(constant)
}

A regra é simples: uma closure @Sendable só pode capturar dados que são eles próprios Sendable e não serão mutados externamente. Para classes, é permitido capturar uma referência fraca weak self se a classe não estiver marcada como Sendable. Isso evita ciclos de retenção clássicos e condições de corrida.

Perguntas frequentes

O que é Sendable em Swift em palavras simples?

Sendable é um marcador que diz ao compilador: «este tipo pode ser transferido com segurança entre threads». Structs e constantes geralmente são Sendable por padrão, classes não, a menos que explicitamente indicado.

Quais tipos estão automaticamente em conformidade com Sendable?

Tipos de valor (struct, enum) com propriedades Sendable, classes finais com estado imutável e todos os tipos básicos Swift: Int, String, Double, Bool, Array, Dictionary, Optional — estão em conformidade com Sendable automaticamente.

O que é @unchecked Sendable?

@unchecked Sendable é uma forma de declarar uma classe como Sendable sem verificações estáticas do compilador. O desenvolvedor garante a segurança por conta própria, muitas vezes através de locks ou operações atômicas.

Por que o Sendable é necessário para Actor?

Actor isola seu estado, mas ao retornar dados para código externo, esses dados cruzam o limite de isolamento. Sendable garante que o destinatário não encontrará condições de corrida ao usar esses dados fora do actor.

Como tornar uma classe Sendable em Swift?

Adicione o protocolo Sendable a uma classe final, cujas propriedades sejam todas constantes de tipos Sendable. Se a classe usar locks, pode-se usar @unchecked Sendable, mas isso requer cautela.

Resumo

  • Sendable — um protocolo marcador para transferência segura de dados entre threads
  • Tipos de valor estão automaticamente em conformidade com Sendable quando as condições são atendidas
  • Classes exigem declaração explícita de Sendable ou @unchecked Sendable
  • Actor retorna dados para código externo apenas através de tipos Sendable
  • @Sendable atributo de closure verifica a correção da captura de variáveis
  • O compilador verifica estaticamente a conformidade com Sendable, prevenindo condições de corrida em tempo de compilação

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também