dispatch_after em Swift: GCD sob o capô — análise 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

dispatch_after em Swift: como o GCD executa tarefas atrasadas sob o capô



Imagine: você está escrevendo um aplicativo em Swift e precisa executar um trecho de código não imediatamente, mas, digamos, após 3 segundos. A primeira coisa que vem à mente é dispatch_after. Mas se você olhar versões antigas do Swift ou o Stack Overflow, verá que esse método mudou. E o principal é que poucos entendem o que realmente acontece internamente no Grand Central Dispatch (GCD) quando dizemos: "Faça isso em 2 segundos".



Neste artigo, não vamos apenas mostrar como escrever dispatch_after no Swift moderno. Vamos mergulhar sob o capô do GCD, analisar filas, threads e timers, para que você possa escrever código assíncrono confiável e eficiente. Vamos lá!



O que é dispatch_after e por que ele se tornou asyncAfter?



Nas versões antigas do Swift (1.x, 2.x), você podia encontrar este código:



dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2 * NSEC_PER_SEC)), dispatch_get_main_queue()) {    print("2 segundos se passaram")}


Esse código funcionava, mas era verboso. A partir do Swift 3, a Apple reformulou toda a API do GCD, tornando-a mais "swift-like". Agora, a mesma funcionalidade fica assim:



DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {    print("2 segundos se passaram")}


Observe: asyncAfter é um método da fila (DispatchQueue), não uma função separada. Essa é uma mudança fundamental: agora você especifica explicitamente em qual fila executar a tarefa.



Como o GCD funciona sob o capô: filas, threads e timers



Para entender dispatch_after (ou asyncAfter), você precisa entender três entidades:



  • DispatchQueue — a fila de tarefas. Pode ser serial ou concorrente.
  • DispatchWorkItem — a tarefa que você coloca na fila. No nosso caso, é uma closure.
  • DispatchTime — o momento em que a tarefa deve ser iniciada. O GCD usa um timer do sistema para rastrear os prazos.


Quando você chama asyncAfter, o GCD não cria uma nova thread. Em vez disso, ele:



  1. Cria um timer que será acionado no horário especificado.
  2. Coloca a tarefa em uma fila especial de tarefas atrasadas (muitas vezes chamada de dispatch timer).
  3. Quando o timer é acionado, o GCD move a tarefa para a fila DispatchQueue normal, onde ela aguarda sua thread.


Se a fila na qual você está colocando a tarefa estiver ocupada com outras tarefas, sua tarefa atrasada pode ser executada após o prazo especificado. Este é um ponto importante: dispatch_after garante que a tarefa não será executada antes do prazo, mas pode ser executada depois.



Exemplo prático: dispatch_after para atualizar a UI



O cenário mais comum é atualizar a interface algum tempo após a ação do usuário. Suponha que você mostre uma mensagem "Salvo" e, após 2 segundos, a remova:



func showTemporaryMessage() {    let messageLabel = UILabel()    messageLabel.text = "Salvo!"    messageLabel.alpha = 1.0    view.addSubview(messageLabel)

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { UIView.animate(withDuration: 0.5) { messageLabel.alpha = 0.0 } completion: { _ in messageLabel.removeFromSuperview() } }}


Observe: usamos DispatchQueue.main porque todas as operações com a UI devem ser executadas na thread principal. Se tivéssemos chamado asyncAfter em uma fila em segundo plano e depois tentado alterar a UI, o aplicativo travaria.



Armadilhas do dispatch_after: vazamentos de memória e captura de self



Um dos erros mais comuns é uma referência forte a self den

Blogs

Book Recommendations