Um ponto de interrupção (breakpoint) é um marcador especial no código no qual o depurador pausa a execução do programa para inspeção de estado. De acordo com o Apple Debugging Guide, os breakpoints permitem ao desenvolvedor visualizar valores de variáveis, a pilha de chamadas e executar passo a passo sem modificar o código fonte. É a principal ferramenta para diagnosticar erros e analisar o comportamento da aplicação em tempo real.
Pontos Principais
Um breakpoint é um marcador ativo colocado em uma linha específica do código fonte, ao alcançá-lo o depurador pausa à força a execução da thread. Nesse momento, o desenvolvedor obtém controle total sobre o estado da aplicação: pode ver os valores de todas as variáveis no escopo atual, examinar a pilha de chamadas, executar expressões arbitrárias e continuar a execução passo a passo. Sem breakpoints, a depuração se resumiria a adicionar infinitas expressões print temporárias e depois removê-las — uma abordagem que polui o código e não oferece controle interativo.
O principal objetivo de um breakpoint é localizar a origem de um erro. Quando uma aplicação se comporta inesperadamente, o desenvolvedor coloca um ponto de interrupção antes da seção suspeita e analisa sequencialmente quais dados entram, como as variáveis mudam e por qual caminho a execução segue. Segundo a Apple, mais de 70% dos erros em aplicativos móveis são identificados precisamente com breakpoints combinados com execução passo a passo, em vez de análise estática de código.
Os breakpoints não afetam o desempenho da compilação de lançamento — eles compilam apenas na configuração Debug. O Xcode possui uma flag especial DEBUG que envolve o código de depuração com diretivas de pré-processador. Isso garante que os breakpoints não cheguem à App Store e não diminuam a velocidade dos usuários finais.
Quando o processador atinge uma linha marcada com um breakpoint, ocorre uma interrupção de hardware ou software. No Xcode, é usado o mecanismo SIGTRAP — um sinal de rastreamento interceptado pelo depurador. O LLDB suspende todas as threads, passa o controle para a interface do Xcode e aguarda o comando do desenvolvedor: continuar (continue), passar por cima (step over), entrar (step into) ou sair (step out).
func fetchUserData(userId: Int) {
// LLDB will stop here if breakpoint is set
let url = URL(string: "https://api.example.com/user/\(userId)")
var request = URLRequest(url: url)
request.httpMethod = "GET"
print("Fetching user \(userId)")
}
No exemplo acima, o breakpoint definido na linha let url = ... permite verificar qual userId foi passado para a função, se a URL foi montada corretamente e quais cabeçalhos estão definidos na requisição antes que a chamada de rede seja executada.
O Xcode fornece cinco tipos principais de breakpoints, cada um resolvendo uma tarefa específica de depuração. Entender suas diferenças permite escolher a ferramenta ideal para cada situação e reduzir o tempo de diagnóstico em 2–3 vezes em comparação com o uso apenas de pontos de interrupção lineares.
| Tipo de Breakpoint | Propósito | Ativação |
|---|---|---|
| Line breakpoint | Parada em uma linha específica de código | Clique no número da linha no editor |
| Conditional breakpoint | Parada quando uma condição é atendida | Clique direito → Edit Breakpoint → Condition |
| Symbolic breakpoint | Parada quando uma função/método é chamado | Breakpoint Navigator → + → Symbolic Breakpoint |
| Exception breakpoint | Parada quando uma exceção é lançada | Breakpoint Navigator → + → Exception Breakpoint |
| Error breakpoint | Parada quando ocorre um erro (Swift) | Breakpoint Navigator → + → Swift Error Breakpoint |
O Line breakpoint é o tipo mais comum. Ele é definido com um único clique no número da linha no editor do Xcode. Quando essa linha é alcançada, a execução é pausada e o desenvolvedor pode inspecionar o estado através do painel Debug Area ou do console LLDB. Segundo estatísticas do Stack Overflow, mais de 85% dos desenvolvedores iOS usam breakpoints lineares como ferramenta principal de depuração, enquanto os outros tipos são usados para cenários específicos como depuração de bibliotecas de terceiros ou captura de exceções.
O Symbolic breakpoint permite parar quando um método ou função específica é chamado, mesmo sem acesso ao código fonte desse método. É indispensável ao depurar frameworks do sistema — por exemplo, para interceptar o momento em que o UIKit chama layoutSubviews. A configuração inclui o nome do símbolo (ex.: -[UIView layoutSubviews] para Objective-C ou UIView.layoutSubviews() para Swift) e parâmetros opcionais: módulo, condição e número de ignorados.
// Symbolic breakpoint to intercept layoutSubviews on UITableView
// Symbol name: -[UITableView layoutSubviews]
// Action: po UITableView.appearance()
class CustomTableView: UITableView {
override func layoutSubviews() {
super.layoutSubviews()
// Symbolic breakpoint here will intercept the call
print("layoutSubviews called")
}
}
Um breakpoint condicional não é acionado em toda execução da linha, mas apenas quando uma expressão lógica especificada é avaliada como true. Isso economiza um tempo enorme ao depurar loops, processamento de arrays e chamadas recursivas — em vez de clicar manualmente em Continue cada vez, o desenvolvedor define uma condição e o depurador para apenas no momento relevante.
Para adicionar uma condição, clique com o botão direito no breakpoint, selecione Edit Breakpoint e insira uma expressão em Swift ou Objective-C no campo Condition. Comparações, operadores lógicos e chamadas de método sem efeitos colaterais são permitidos. O Xcode avalia a expressão no contexto do programa parado e, se for verdadeira, o depurador captura o estado.
for index in 0..<1000 {
// Breakpoint with condition: index == 500
// The debugger will stop only on the 501st iteration
processItem(at: index)
}
Além de uma condição, um breakpoint pode executar ações automáticas sem parar o programa. Isso é implementado através da opção Automatically continue after evaluating nas configurações do breakpoint. As ações incluem: exibir valores no console (po variable), reproduzir um sinal sonoro, executar um comando LLDB arbitrário ou rodar um script shell. Essa abordagem substitui expressões print temporárias e permite registrar dados sem modificar o código fonte.
// Breakpoint with action: po “Index: \(index), value: \(items[index])”
// Automatically continue = true → program does not stop
func processItems(_ items: [String]) {
for (index, item) in items.enumerated() {
// Here the breakpoint logs every iteration without stopping
print("Processing \(item)")
}
}
Essa técnica é especialmente útil ao depurar atualizações de UI — por exemplo, para registrar todas as alterações de frame sem interferir no código do controlador. Segundo Ray Wenderlich, usar ações de breakpoint em vez de expressões print temporárias reduz o tempo de depuração em 30–40% por não precisar limpar o código depois.
Embora o Xcode forneça uma interface gráfica conveniente, o LLDB suporta dezenas de comandos para gerenciamento programático de pontos de interrupção diretamente do console do depurador. Isso oferece capacidades não disponíveis através da GUI: desativação em massa de breakpoints por expressão regular, definição de breakpoints em bibliotecas carregadas dinamicamente e criação de gatilhos complexos de várias etapas.
| Comando LLDB | Descrição | Exemplo |
|---|---|---|
| breakpoint set | Definir um breakpoint | breakpoint set -f ViewController.swift -l 42 |
| breakpoint list | Listar todos os breakpoints | breakpoint list |
| breakpoint disable | Desativar um breakpoint por número | breakpoint disable 1 |
| breakpoint delete | Excluir um breakpoint | breakpoint delete 1.2 |
| breakpoint modify | Modificar condição ou ação | breakpoint modify -c “i > 100” 1 |
(lldb) breakpoint set -f LoginViewController.swift -l 15 -c "email.isEmpty"
Breakpoint 1: 15 locations added.
(lldb) breakpoint modify 1 -C "po email" -G true
(lldb) breakpoint list
1: name = 'LoginViewController.swift:15', condition = 'email.isEmpty'
1.1: addr = 0x1000a3b40
O LLDB suporta a definição de breakpoints por expressão regular para nomes de funções. Isso permite interceptar todos os métodos que correspondem a um padrão — por exemplo, todos os métodos que começam com handle em uma classe específica. Essa abordagem é usada durante refatoração e análise de código desconhecido quando você precisa entender quais métodos estão envolvidos no processamento de um evento específico.
(lldb) breakpoint set -r "handle[A-Z]" -s DataManager
Breakpoint 2: 6 locations.
(lldb) breakpoint set -r ".*Error.*"
Breakpoint 3: 23 locations.
Um Exception breakpoint interrompe a execução do programa quando qualquer exceção é lançada — tanto erros Objective-C quanto Swift. No Xcode, você pode configurar a interceptação apenas de exceções Objective-C, apenas erros Swift ou todos os tipos. É uma ferramenta indispensável quando a aplicação trava sem uma indicação clara da localização no código — por exemplo, ao acessar um objeto desalocado.
O Swift Error Breakpoint é um tipo especializado introduzido no Xcode 11. Ele intercepta o momento em que uma função Swift lança um erro via throw, antes que ele chegue a um bloco catch. Isso permite ver qual função gerou o erro e com quais argumentos, o que é crítico ao depurar cadeias de chamadas complexas com vários níveis de tratamento de erros.
enum NetworkError: Error {
case invalidURL
case noData
case decodingFailed(String)
}
func loadUserProfile(id: Int) throws -> UserProfile {
guard id > 0 else {
throw NetworkError.invalidURL
}
// Swift Error Breakpoint will stop here on throw
return UserProfile(id: id, name: "Test")
}
Breakpoints simbólicos também são eficazes ao depurar KVO e NotificationCenter. Definindo um breakpoint em observeValue(forKeyPath:of:change:context:), o desenvolvedor pode interceptar todas as notificações KVO na aplicação, ajudando a diagnosticar atualizações inesperadas de UI ou condições de corrida relacionadas à observação de propriedades.
O uso eficaz de breakpoints vai muito além de simplesmente parar em uma linha. Desenvolvedores experientes combinam tipos de pontos de interrupção com scripts LLDB, zonas de parada temporárias e exportação de configurações para depuração reproduzível. Vamos ver as técnicas mais úteis, respaldadas pela prática de engenheiros da Apple e Google.
Ao depurar bugs difíceis de encontrar, use uma combinação de um breakpoint na entrada do método e um watchpoint na mudança de uma variável chave. Defina um breakpoint linear antes da atribuição e, em seguida, crie um watchpoint na variável através do comando LLDB watchpoint set variable. Quando o valor mudar, o depurador parará independentemente de onde no código a modificação ocorreu. Segundo a Google, essa abordagem pode encontrar a origem de uma condição de corrida em 90% dos casos em uma única sessão de depuração.
(lldb) watchpoint set variable self->_balance
Watchpoint 1: addr = 0x600000c4b80 size = 8
state = enabled type = w
watchpoint spec: 'self._balance'
(lldb) watchpoint list
1: location = 0x600000c4b80, type = write, variable = '_balance'
O Xcode permite agrupar breakpoints através do Breakpoint Navigator. Crie um grupo separado para cada cenário — por exemplo, “login”, “compra”, “erros de rede”. Ao testar uma funcionalidade específica, ative apenas o grupo correspondente, desativando os demais. Isso evita disparos falsos e acelera a depuração em projetos grandes onde o número de breakpoints pode exceder várias dezenas. Exportar um grupo para um arquivo permite compartilhar a configuração com colegas através do controle de versão.
Para cenários complexos, o LLDB suporta a execução de scripts Python quando um breakpoint é acionado. Na ação do breakpoint, especifique script import my_debug_helper; my_debug_helper.log_state(). Isso abre possibilidades ilimitadas: coleta automática de estatísticas, comparação de estados entre chamadas, geração de relatórios de cobertura de depuração. Segundo a Apple, a API Python do LLDB é usada no Xcode Cloud para análise automática de crashes durante testes de CI.
Perguntas Frequentes
Breakpoints inativos não afetam o desempenho — eles compilam apenas na configuração Debug. Pontos ativos diminuem a execução devido ao mecanismo de interrupção de hardware, mas apenas durante a depuração.
Sim, através de um Symbolic breakpoint pelo nome do método ou função. O LLDB parará quando o símbolo for chamado, mesmo que o código fonte não esteja disponível. Adicionalmente, você pode usar o desmontador do LLDB para navegação passo a passo.
Step Over executa a linha atual inteiramente (incluindo chamadas de função) e para na próxima linha. Step Into entra dentro da função chamada, permitindo depurá-la passo a passo. Step Out retorna o controle para o chamador.
Breakpoints são salvos automaticamente em xcuserdata dentro do projeto. Para compartilhar com colegas, use exportação via Breakpoint Navigator → Share. O arquivo .xcbkptlist pode ser adicionado ao repositório se a depuração for em equipe.
Verifique a configuração Debug da compilação, a atividade do breakpoint (ícone azul), a correção do símbolo para breakpoints simbólicos e se o código fonte corresponde ao binário executável — geralmente o Clean Build Folder ajuda.
Resumo
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.
Leia também