Tratamento de erros em Swift: try/catch e técnicas avançadas

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Tratamento de Erros em Swift: try/catch e muito mais



No desenvolvimento moderno para iOS e macOS, a confiabilidade do aplicativo é um dos principais indicadores de qualidade. Um tratamento adequado de erros em Swift não apenas evita falhas inesperadas, mas também torna o código mais legível e previsível. Neste artigo, abordaremos não apenas o mecanismo clássico try/catch, mas também abordagens alternativas, incluindo o tipo Result, o operador defer e padrões avançados.



Fundamentos: o protocolo Error e a palavra-chave throws



Em Swift, os erros são representados por tipos que estão em conformidade com o protocolo Error. Na maioria das vezes, usamos enumerações (enum) para isso. Para que uma função possa lançar um erro, a palavra-chave throws é usada em sua declaração.



enum NetworkError: Error {    case noInternet    case serverError(code: Int)    case timeout}

func fetchData(from url: String) throws -> Data { guard url.hasPrefix("https") else { throw NetworkError.serverError(code: 400) } // ... simulação de carregamento return Data()}


Observe: se uma função for marcada com throws, o código chamador é obrigado a tratar o possível erro usando try, try? ou try!.



Construção do-catch: a abordagem clássica



A maneira mais comum de tratamento é o bloco do-catch. Você coloca o código potencialmente perigoso dentro do do e, no catch, descreve o que fazer com cada erro específico.



do {    let data = try fetchData(from: "http://example.com")    print("Dados recebidos: \\(data)")} catch NetworkError.noInternet {    print("Sem conexão com a internet")} catch NetworkError.serverError(let code) {    print("Erro do servidor com código: \\(code)")} catch {    print("Erro desconhecido: \\(error.localizedDescription)")}


Importante: o último bloco catch sem padrão captura todos os erros restantes. Esta é uma boa prática para não perder exceções inesperadas.



try? e try!: alternativas rápidas



Se o tipo do erro não for importante para você e você só precisar saber se a função foi executada com sucesso, use try?. Em caso de erro, o resultado será nil.



if let data = try? fetchData(from: "https://valid.com") {    print("Sucesso: \\(data)")} else {    print("Erro ao carregar")}


O operador try! é uma "bomba-relógio". Ele suprime o tratamento de erros e causa uma falha no aplicativo se um erro ocorrer. Use-o apenas nos casos em que você tem 100% de certeza de que não há erro (por exemplo, ao carregar um recurso embutido).



let data = try! fetchData(from: "https://trusted-source.com")// Se houver erro — o aplicativo irá travar


Tipo Result: abordagem funcional



A partir do Swift 5, o tipo Result<Success, Failure> foi adicionado à biblioteca padrão. É um closure que pode conter um valor de sucesso ou um erro. Essa abordagem é especialmente conveniente em código assíncrono e em funções de callback (completion handlers).



func fetchDataResult(from url: String) -> Result<Data, NetworkError> {    guard url.hasPrefix("https") else {        return .failure(.serverError(code: 400))    }    return .success(Data())}

// Usolet result = fetchDataResult(from: "http://bad.com")switch result {case .success(let data): print("Dados: \\(data)")case .failure(let error): print("Erro: \\(error)")}


A vantagem do Result é que você não se esquece de tratar o erro, pois o compilador força você a

Blogs

Book Recommendations