Tratamento de Erros em Swift: try/catch e muito mais — guia completo
O tratamento de erros é um dos tópicos principais no desenvolvimento para iOS e macOS. A linguagem Swift implementa um sistema de gerenciamento de falhas poderoso e elegante que vai muito além do simples try/catch. Compreender esses mecanismos permite escrever código confiável, previsível e seguro. Neste artigo, abordaremos todos os aspectos: desde a declaração básica de erros até técnicas avançadas com valores opcionais e desinicializadores.
Fundamentos: protocolo Error e a palavra-chave throws
Em Swift, qualquer erro deve estar em conformidade com o protocolo Error. Geralmente, usamos enumerações (enum) para isso. Vejamos um exemplo simples — validação de senha:
enum PasswordError: Error { case tooShort case missingDigit case missingUppercase}
func validatePassword(_ password: String) throws { guard password.count >= 8 else { throw PasswordError.tooShort } guard password.rangeOfCharacter(from: .decimalDigits) != nil else { throw PasswordError.missingDigit } guard password.rangeOfCharacter(from: .uppercaseLetters) != nil else { throw PasswordError.missingUppercase } print("Senha válida")}A palavra-chave throws na declaração da função informa ao compilador que a execução pode ser interrompida por um erro. Chamar essa função requer uma sintaxe especial.
Construção do-catch e a palavra-chave try
Para lidar com possíveis erros, usamos o bloco do-catch com a marcação try antes da chamada:
do { try validatePassword("Hello123") print("Sucesso!")} catch PasswordError.tooShort { print("Erro: senha muito curta")} catch PasswordError.missingDigit { print("Erro: senha não contém dígito")} catch PasswordError.missingUppercase { print("Erro: senha não contém letra maiúscula")} catch { print("Erro desconhecido: \\(error)")}Observe o último bloco catch — ele captura quaisquer erros não tratados anteriormente. Isso é um requisito obrigatório: o compilador Swift verifica se todos os erros possíveis foram tratados.
try? e try! — versões simplificadas de tratamento
Às vezes, você não precisa de controle total sobre os erros. O Swift oferece duas versões simplificadas:
- try? — converte o erro em um valor opcional
nil. Se não houver erro, retorna o resultado encapsulado emOptional. - try! — afirma que não haverá erro. Se ele ocorrer, o aplicativo será encerrado abruptamente (runtime crash).
// try? — ignorar erro com segurançaif let _ = try? validatePassword("weak") { print("Senha aprovada na verificação")} else { print("Senha não aprovada")}
// try! — apenas se você tiver 100% de certezalet result = try! validatePassword("StrongPass1") // Crash se a senha for inválidaUse try! apenas em situações onde o erro é teoricamente impossível (por exemplo, ao carregar um recurso incorporado no bundle do aplicativo).
Técnicas avançadas: rethrows, defer e Result
Rethrows (relançamento de erros)
A palavra-chave rethrows é aplicada a funções de ordem superior que recebem uma closure capaz de lançar um erro. A função em si não lança o erro, mas o repassa a partir da closure:
func processItems(_ items: [String], using validator: (String) throws -> Void) rethrows { for item in items { try validator(item) }}
// Usodo { try processItems(["Hello", "World123"], using: validatePassword)} catch { print("Erro de processamento: \\(error)")}Isso permite escrever funções wrapper flexíveis sem duplicar o código de tratamento de erros.
Blogs
Book Recommendations
Leia também
WebAssembly e Kotlin: Guia Completo de Integração
Princípios SOLID em JavaScript: teoria e prática
Enterprise Go: como escrever código que não envergonha mostrar ao CTO
Escrevendo documentação para projetos JavaScript: melhores práticas
Segurança de aplicações Rust: top 10 vulnerabilidades e sua prevenção
Blogs
Book Recommendations
Leia também
Princípios SOLID em JavaScript: teoria e prática
Segurança de aplicações Rust: top 10 vulnerabilidades e sua prevenção