Ao desenvolver um app, o pedido para “adicionar só um botão de undo” aparece com mais frequência do que você imagina.
Quando você tenta adicionar undo, o código pode virar uma verdadeira bagunça. Por causa de um único botão, a lógica de reversão acaba espalhada pelo código de exclusão, movimentação e edição.
Quem organiza isso é justamente o padrão Command do Swift.
Neste artigo, vamos entender por que o padrão Command é a base do undo e revisar a estrutura mínima de código para usá-lo na prática. O foco está em um formato que você pode adicionar imediatamente ao projeto, e não em teoria complexa.
O que é o padrão Command? Resumo em uma linha
Vamos começar com uma definição rápida.
O padrão Command encapsula em um objeto a ação de “fazer algo” e reúne execução e cancelamento em uma única unidade.
Em vez de executar a lógica diretamente ao tocar em um botão, criamos um objeto Command que diz: “execute esta ação”.
Esse comando contém tanto a forma de executar (execute) quanto a forma de desfazer (undo).
Em resumo:
- Transforme ações em objetos — exclusão, movimentação e entrada viram comandos individuais
- Cada comando mantém execute() e undo() em par
- Empilhe os comandos executados
- Para desfazer, retire um comando da pilha e chame undo()
Graças a essa estrutura, a lógica de reversão fica dentro de cada comando, em vez de espalhada pelo código.
Vamos criar primeiro o protocolo Command em Swift
Primeiro, definimos o contrato que todo comando deve seguir: o protocolo.
Este é o esqueleto mínimo que exige execução e undo.
protocol Command {
func execute() // Executar ação
func undo() // Desfazer execução
}
Só esses dois métodos são necessários.
Agora vamos criar um comando concreto com uma ação real. Por exemplo, um comando que adiciona texto.
O código abaixo adiciona texto e o remove novamente quando é desfeito.
final class AddTextCommand: Command {
private let document: Document
private let text: String
init(document: Document, text: String) {
self.document = document
self.text = text
}
func execute() { document.content += text }
func undo() { document.content.removeLast(text.count) }
}
execute adiciona o texto, e undo remove exatamente o que foi adicionado. Ter execução e undo no mesmo objeto é todo o padrão.
A chave do undo é a pilha
Depois de criar os comandos, você precisa de um “gerenciador” para cuidar deles. Esse papel costuma ser chamado de Invoker.
O gerenciador empilha os comandos executados, um após o outro.
Ao tocar em undo, retire o comando mais recente e chame undo(). Desfazer primeiro o que foi feito por último é a ordem natural do undo.
Este é o esqueleto do gerenciador.
final class CommandManager {
private var undoStack: [Command] = []
func run(_ command: Command) {
command.execute()
undoStack.append(command) // Salvar na pilha após a execução
}
func undo() {
guard let last = undoStack.popLast() else { return }
last.undo() // Desfazer começando pelo último
}
}
Agora o uso fica muito simples.
Em buttonTapped, chame manager.run(command); no botão de undo, basta chamar manager.undo().
O CommandManager cuida da ordem de reversão e do gerenciamento da pilha, mantendo o código da tela limpo.
Se você também precisar de redo, armazene os comandos desfeitos separadamente em redoStack. Como a estrutura é simétrica, é fácil estendê-la.
Quando usar e quando evitar o padrão Command?
O padrão Command também não é uma solução universal. Veja na tabela quando ele se encaixa e quando é exagero.
| Situação | Padrão Command |
|---|---|
| É necessário undo e redo | Muito adequado |
| É preciso manter o histórico de operações | Adequado |
| Enfileirar ações para executar depois | Adequado |
| Um botão simples sem nada para desfazer | Exagero; use uma função |
O padrão Command se destaca quando você precisa de undo ou histórico. Apps de desenho, editores de texto, cancelamento de pagamentos e undo em jogos são exemplos típicos.
Por outro lado, aplicar o padrão Command a um botão que apenas navega entre telas só aumenta o código.
Transformar todos os botões em comandos pode gerar rapidamente muitos arquivos, então aplique o padrão apenas a ações que precisam ser desfeitas.
Resumo
Adicionar undo pode parecer complicado, mas, com o padrão Command como base, tudo funciona de forma mais organizada do que você espera.
Comece aplicando as três peças de hoje — protocolo, comandos concretos e gerenciador — a uma tela pequena. Quando a estrutura ficar familiar, as extensões para redo e histórico virão naturalmente. Adicione um botão de undo ao seu app com confiança.

