Trabalhando com filas de tarefas em Swift: da teoria aos projetos reais
\nNo desenvolvimento moderno para iOS e macOS, a velocidade de resposta da interface é um fator chave para o sucesso de um aplicativo. Cada vez que você executa uma operação pesada (carregamento de imagem, análise de JSON, trabalho com banco de dados) na thread principal, o usuário vê um "travamento" da interface. A solução são as filas de tarefas. Neste artigo, vamos abordar três abordagens principais para trabalhar com filas em Swift: o clássico GCD, o de alto nível OperationQueue e o moderno async/await. Você receberá exemplos de código prontos para uso e saberá qual abordagem escolher para cada tarefa específica.
\n\n1. Grand Central Dispatch (GCD): início rápido com DispatchQueue
\nGrand Central Dispatch é uma biblioteca de baixo nível para gerenciar a execução paralela de código. Ela está na base da multithreading em Swift e continua sendo a ferramenta mais performática para tarefas simples em segundo plano.
\n\nTipos principais de filas:
\n- \n
main— fila serial da thread principal (todas as atualizações de UI apenas aqui). \n global(qos:)— filas paralelas com prioridades (userInteractive, userInitiated, utility, background). \n custom(label:)— sua própria fila (pode ser serial ou paralela). \n
Exemplo: carregamento de imagem e atualização de UI
\nimport UIKit\n\nclass ImageLoader {\n func loadImage(from url: URL, completion: @escaping (UIImage?) -> Void) {\n DispatchQueue.global(qos: .userInitiated).async {\n guard let data = try? Data(contentsOf: url),\n let image = UIImage(data: data) else {\n DispatchQueue.main.async {\n completion(nil)\n }\n return\n }\n DispatchQueue.main.async {\n completion(image)\n }\n }\n }\n}\n\nDica prática: Sempre use .userInitiated para tarefas que o usuário espera imediatamente (por exemplo, abrir uma imagem). Para sincronização de dados em segundo plano, use .background.
2. OperationQueue: gerenciamento de dependências e cancelamento de tarefas
\nQuando a lógica se torna mais complexa (é necessário cancelar uma tarefa, definir a ordem de execução ou limitar o número de operações paralelas), o OperationQueue entra em cena. Ao contrário do GCD, as operações são objetos que podem ser reutilizados e controlados.
Principais recursos:
\n- \n
- Cancelamento de tarefas via
cancel(). \n - Dependências (
addDependency) — a tarefa B será executada somente após a tarefa A. \n - Controle do número máximo de operações paralelas (
maxConcurrentOperationCount). \n
Exemplo: carregamento de várias imagens com limite de paralelismo
\nimport UIKit\n\nclass BatchImageDownloader {\n private let queue: OperationQueue = {\n let q = OperationQueue()\n q.maxConcurrentOperationCount = 3 // No máximo 3 downloads simultâneos\n q.qualityOfService = .userInitiated\n return q\n }()\n \n func downloadImages(from urls: [URL], completion: @escaping ([UIImage]) -> Void) {\n var images: [UIImage] = []\n let syncQueue = DispatchQueue(label: "sync.images")\n \n let finishOperation = BlockOperation {\n DispatchQueue.main.async {\n completion(images)\n }\n }\n \n for url in urls {\n let operation = BlockOperation {\n guard let data = try? Data(contentsOf: url),\n let image = UIImage(data: data) else { return }\n syncQueue.async {\n images.append(image)\n }\n }\n