OperationQueue — o que é, Operation e gerenciamento de tarefas

Autor: IT Sectr Publicado: 2026-03-16 Tempo de leitura: 8 min

OperationQueue é uma fila de tarefas de alto nível no iOS e macOS construída sobre o Grand Central Dispatch. De acordo com Apple Developer Documentation, 2026, OperationQueue gerencia instâncias de Operation — objetos que encapsulam uma unidade de trabalho. Ao contrário do DispatchQueue, o OperationQueue suporta dependências entre operações, prioridades, observação KVO e cancelamento de tarefas em execução. OperationQueue gerencia automaticamente um pool de threads, distribuindo as operações pelos recursos disponíveis do sistema.

Pontos Principais

  • OperationQueue — uma fila de alto nível com suporte a dependências entre operações
  • Operation — uma classe abstrata para encapsular uma unidade de trabalho com estado
  • BlockOperation — uma implementação simplificada de Operation para um único bloco de código
  • Dependências definem a ordem de execução: a operação B é executada após A
  • Cancelamento de operações é suportado através da propriedade isCancelled compatível com KVO

O que é OperationQueue e Operation

OperationQueue é uma classe do framework Foundation que gerencia a execução de objetos Operation. Ao contrário do DispatchQueue, o OperationQueue não exige especificar explicitamente o modo serial ou concorrente — o número de operações executadas simultaneamente é controlado pela propriedade maxConcurrentOperationCount. O valor 1 torna a fila sequencial, qualquer outro valor a torna concorrente.

Operation é uma classe abstrata que representa uma unidade de trabalho. Cada operação tem um estado: ready, executing, finished ou cancelled. Os estados são compatíveis com KVO (Key-Value Observing), permitindo reagir a mudanças — por exemplo, atualizar a interface quando uma operação é concluída. O Operation gerencia automaticamente os flags isExecuting e isFinished.

De acordo com a Apple (2026), o OperationQueue usa GCD internamente, mas adiciona funcionalidades não disponíveis no DispatchQueue: dependências, prioridades e cancelamento de operações. Se o aplicativo entrar em segundo plano, o OperationQueue suspende a execução e a retoma ao retornar. OperationQueue também considera automaticamente o número de núcleos da CPU e seleciona o número ideal de threads.

Ciclo de Vida de uma Operation

Cada operação passa por quatro estados: pending (pendente), ready (pronta), executing (executando) e finished (concluída). O estado cancelled pode ocorrer em qualquer estágio antes da conclusão. As transições de estado são rastreadas via KVO — esta é a base para atualizações reativas de interface. OperationQueue remove automaticamente as operações concluídas da fila e notifica as operações dependentes de que seu pré-requisito foi cumprido, acionando sua execução.

Operation e BlockOperation: Implementação de Tarefas

Operation é uma classe abstrata que requer a sobrescrita do método main() ou start(). O código da tarefa é colocado no método main(), e os estados isExecuting e isFinished são gerenciados automaticamente. Para operações assíncronas, é necessário sobrescrever start() e gerenciar manualmente os flags de estado.

BlockOperation é uma implementação concreta de Operation que executa um ou mais blocos de código. O BlockOperation se torna concorrente se você adicionar vários blocos através de addExecutionBlock(). A operação é concluída somente após todos os blocos adicionados serem executados. BlockOperation é uma alternativa conveniente para tarefas simples sem herança.

CaracterísticaOperationBlockOperation
Tipo de ClasseAbstrataConcreta
HerançaExigidaNão exigida
AssincroniaGerenciamento manual de KVOAutomática
Blocos de CódigoUm em main()Um ou vários
UsoTarefas complexas com estadoTarefas simples únicas
Adequado paraDependências, cancelamento, progressoBlocos rápidos, conclusão
MemóriaMaior devido a KVO e estadoMínima, leve

Criando uma Operation Personalizada

Para criar uma operação personalizada, herde de Operation e sobrescreva main(). Dentro, verifique o flag isCancelled antes de operações custosas para garantir um cancelamento rápido. Isso é crítico para baixar arquivos grandes ou processamento em lote de dados. A escolha entre Operation e BlockOperation depende da complexidade da tarefa: para ações simples únicas, BlockOperation é suficiente; para lógica reutilizável com estado, herde de Operation.

Dependências e Prioridades de Operações

Dependências são a principal vantagem do OperationQueue sobre o DispatchQueue. O método addDependency(_:) especifica que a operação B é executada somente após a operação A ser concluída. As dependências formam um grafo acíclico dirigido (DAG): se uma dependência cíclica for adicionada, a fila a ignora e as operações não são iniciadas.

Prioridade de uma operação é definida através da propriedade queuePriority com valores: .veryLow, .low, .normal, .high, .veryHigh. A prioridade afeta a ordem de início entre as operações prontas, mas não substitui as dependências. OperationQueue primeiro resolve as dependências, depois aplica a prioridade entre as operações disponíveis.

Exemplo Prático de Dependências

Um cenário típico — carregar dados de perfil: primeiro carregar o usuário, depois com base em seu id carregar amigos e posts. Definir uma dependência entre carregar o usuário e carregar amigos garante a ordem correta sem handlers de conclusão aninhados.

Limitando a Concorrência

A propriedade maxConcurrentOperationCount limita o número de operações executadas simultaneamente. O valor 1 cria uma fila sequencial, o valor padrão (NSOperationQueueDefaultMaxConcurrentOperationCount) é ótimo para o sistema e depende da carga atual do dispositivo. A configuração adequada deste parâmetro evita o consumo excessivo de recursos: para carregar imagens, 4–6 operações concorrentes são suficientes; para tarefas intensivas de CPU, use o número de núcleos do processador.

OperationQueue vs DispatchQueue: Comparação

Escolher entre OperationQueue e DispatchQueue depende da complexidade da tarefa. DispatchQueue é uma ferramenta leve para chamadas assíncronas simples. OperationQueue é uma solução mais pesada para cenários complexos com muitas tarefas inter-relacionadas. A Apple recomenda começar com DispatchQueue e mudar para OperationQueue apenas quando dependências ou cancelamento forem necessários. Para a maioria dos projetos iOS, uma combinação de ambas as ferramentas oferece um equilíbrio ideal entre desempenho e flexibilidade.

  • DispatchQueue — leve, rápida, sem a sobrecarga de objetos Operation
  • OperationQueue — suporta dependências, cancelamento, KVO e prioridades
  • DispatchQueue — ideal para tarefas async/asyncAfter simples e sincronização serial
  • OperationQueue — indispensável para algoritmos passo a passo com estágios sequenciais
  • DispatchQueue — integra-se com Swift Concurrency (async/await) via Continuation

De acordo com Ray Wenderlich (2025), em grandes projetos iOS, o OperationQueue é usado para carregar conteúdo com progresso e cancelamento, enquanto o DispatchQueue é usado para todas as outras operações assíncronas. A proporção é de aproximadamente 20 para 80 a favor do DispatchQueue.

Exemplos de Código com OperationQueue em Swift

Vamos ver três exemplos: um BlockOperation simples, uma Operation personalizada com dependências e uma operação cancelável para carregamento de dados.

BlockOperation com Conclusão

O caso mais simples — executar um bloco no OperationQueue e tratar o resultado através de completionBlock. Cada Operation tem uma propriedade completionBlock embutida, chamada após main() terminar.

swift
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
    let data = NetworkService.fetchData()
    OperationQueue.main.addOperation {
        self.updateUI(data)
    }
}
queue.addOperation(operation)

Dependências Entre Operações

A dependência garante que parseOperation só inicie após downloadOperation ser concluída. Isso elimina a necessidade de callbacks aninhados.

swift
let download = BlockOperation { self.downloadJSON() }
let parse = BlockOperation { self.parseJSON() }
parse.addDependency(download)

let queue = OperationQueue()
queue.addOperations([download, parse], waitUntilFinished: false)

Operação Personalizada Cancelável

Sobrescreva main() com verificações periódicas de isCancelled. Isso permite que a operação pare imediatamente ao ser cancelada, sem esperar a conclusão de uma operação custosa.

swift
class ImageLoadOperation: Operation {
    override func main() {
        guard !self.isCancelled else { return }
        let image = self.downloadImage()
        guard !self.isCancelled else { return }
        OperationQueue.main.addOperation { self.display(image) }
    }
}

Cancelamento de Operações e Observação KVO

O cancelamento de uma operação define o flag isCancelled como true, mas não interrompe um método main() já em execução. O código dentro de main() deve verificar isCancelled por si só e terminar quando necessário. Esta é uma decisão arquitetural da Apple — permitindo que o desenvolvedor libere recursos adequadamente ao cancelar.

A observação KVO das propriedades isFinished e isExecuting permite reagir à conclusão de operações sem callbacks explícitos. OperationQueue remove automaticamente as operações concluídas da fila, mas elas permanecem na memória enquanto houver referências fortes para elas. KVO é a base para integrar OperationQueue com frameworks reativos como RxSwift ou Combine.

Tratamento de Cancelamento via KVO

Assinar isCancelled via KVO permite atualizar a interface ao cancelar uma operação — por exemplo, mostrar um placeholder em vez de um download cancelado. A propriedade isCancelled é compatível com KVO, tornando-a conveniente para pipelines reativos.

Melhores Práticas para Trabalhar com OperationQueue

Não crie grandes quantidades de operações — cada Operation é um objeto separado na memória. Se uma tarefa é curta e não requer dependências, use DispatchQueue diretamente. OperationQueue é justificada para cenários complexos com dependências explícitas, cancelamento e monitoramento de progresso.

Verifique isCancelled antes de operações custosas dentro do método main(). Em casos de download de arquivos ou processamento de imagens, verificar após cada passo significativo garante uma resposta rápida ao cancelamento. Use if isCancelled { return } no início de main() e após cada operação importante.

Gerencie completionBlock adequadamente. A propriedade completionBlock de uma operação é chamada após main() terminar, mesmo se a operação foi cancelada. Verifique isCancelled dentro de completionBlock para evitar atualizar a interface com dados errôneos. OperationQueue.main é uma fila thread-safe para operações de interface, similar ao DispatchQueue.main.

Evite dependências cíclicas — elas fazem com que nenhuma das operações no ciclo seja iniciada. OperationQueue não detecta ciclos automaticamente: se A depende de B e B depende de A, ambas permanecerão no estado ready para sempre. Planeje o grafo de dependências com antecedência.

Perguntas Frequentes

Como o OperationQueue difere do DispatchQueue?

OperationQueue é construído sobre o GCD e adiciona dependências, prioridades, KVO e cancelamento de operações. DispatchQueue é uma ferramenta mais leve para tarefas assíncronas simples sem essas capacidades.

Como tornar a fila sequencial?

Defina a propriedade maxConcurrentOperationCount como 1. Isso transforma OperationQueue em uma fila sequencial mantendo todas as vantagens — dependências, prioridades e cancelamento.

Pode-se cancelar uma operação em execução?

O método cancel() define o flag isCancelled mas não interrompe o método main() em execução. O código da operação deve verificar isCancelled por si só e terminar. O cancelamento funciona apenas para operações pendentes e prontas.

Quando devo usar Operation em vez de BlockOperation?

Você deve herdar de Operation quando precisar de gerenciamento de estado, assincronia ou reutilização de lógica. BlockOperation é adequado para tarefas simples únicas sem herança.

O OperationQueue bloqueia a thread principal?

Não, a menos que você chame waitUntilFinished com o parâmetro true na thread principal. As operações são executadas em threads de fundo por padrão, e os resultados são retornados através de OperationQueue.main.

Resumo

  • OperationQueue — uma fila de alto nível com dependências, prioridades e cancelamento de operações
  • Operation — uma classe abstrata para encapsular trabalho com estado compatível com KVO
  • BlockOperation — uma implementação simplificada para um ou mais blocos de código
  • Dependências definem a ordem de execução entre operações através de um grafo sem ciclos
  • Cancelamento requer verificação manual de isCancelled dentro do método main() da operação
  • maxConcurrentOperationCount = 1 transforma a fila em modo sequencial
  • OperationQueue vs DispatchQueue — escolha OperationQueue apenas quando precisar de dependências ou KVO

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