Programação Assíncrona em Swift: guia completo com exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução à programação assíncrona em Swift

Aplicativos móveis e de desktop modernos em Swift (iOS/macOS) cada vez mais exigem a execução de operações longas — carregamento de dados da rede, trabalho com arquivos, processamento de imagens — sem bloquear a interface do usuário. Até recentemente, os desenvolvedores usavam closures (completion handlers) e Grand Central Dispatch (GCD), o que levava ao chamado "inferno de callbacks" e dificultava a leitura do código. Com o lançamento do Swift 5.5, a Apple apresentou um modelo fundamentalmente novo de programação assíncrona, baseado nas palavras-chave async e await, bem como em atores e estruturas Task. Neste guia, abordaremos todos os conceitos-chave com exemplos práticos.



1. Fundamentos de async/await em Swift

A palavra-chave async indica que uma função ou método pode pausar sua execução para aguardar o resultado de uma operação assíncrona. A chamada dessa função é marcada com a palavra await. Isso permite escrever código assíncrono de forma tão linear quanto o código síncrono.



// Declarando uma função assíncronafunc fetchUserData(from url: URL) async throws -> Data {    let (data, _) = try await URLSession.shared.data(from: url)    return data}

// Usando-a no contexto de uma taskTask { do { let url = URL(string: "https://api.example.com/user")! let userData = try await fetchUserData(from: url) print("Dados recebidos: \\(userData.count) bytes") } catch { print("Erro ao carregar: \\(error.localizedDescription)") }}


Observe: a chamada await pausa a tarefa atual, mas não bloqueia a thread. O próprio sistema alterna o contexto quando o resultado estiver pronto, tornando o código eficiente e seguro.



2. Atores (Actors) — trabalho seguro com estado

A assincronicidade adiciona o problema de data race. Para resolvê-lo, o Swift introduziu os atores. Um ator é um tipo de referência que isola seu estado e garante que apenas uma tarefa possa acessar suas propriedades mutáveis a qualquer momento.



actor Counter {    private var value = 0        func increment() {        value += 1    }        func getValue() -> Int {        return value    }}

// Usando o atorlet counter = Counter()

Task { await counter.increment() let currentValue = await counter.getValue() print("Valor atual: \\(currentValue)")}


A palavra-chave actor torna automaticamente todos os métodos e propriedades (exceto os imutáveis) assíncronos para acesso externo. Isso evita bloqueios e deadlocks, comuns no gerenciamento manual de locks (NSLock, DispatchSemaphore).



3. TaskGroup e execução paralela de tarefas

Quando é necessário executar várias operações assíncronas independentes em paralelo, use TaskGroup. É uma estrutura que permite iniciar tarefas filhas e coletar seus resultados.



func fetchMultipleUsers(ids: [Int]) async throws -> [User] {    try await withThrowingTaskGroup(of: User.self) { group in        var users: [User] = []                for id in ids {            group.addTask {                let url = URL(string: "https://api.example.com/users/\\(id)")!                let data = try await URLSession.shared.data(from: url)                return try JSONDecoder().decode(User.self, from: data.0)            }        }                for try await user in group {            users.append(user)        }        return users    }}

// UsoTask { let users = try? await fetchMultipleUsers(ids: [1, 2, 3, 4, 5]) print("Usuários carregados: \\(users?.count ?? 0)")}


O método withThrowi

Blogs

Book Recommendations