Aula 144: Tratamento Avançado de Erros e Tipos de Resultado
Swift oferece mecanismos robustos para tratamento de erros e o tipo Result
para lidar com sucessos e falhas de forma limpa e concisa. Nesta aula, vamos explorar técnicas avançadas de tratamento de erros e nos aprofundar no tipo Result
para gerenciar tarefas assíncronas.
Noções Básicas de Tratamento de Erros
Em Swift, você pode definir seus próprios tipos de erro, conformando-se ao protocolo Error
. Isso permite que você crie tipos de erro estruturados que podem representar vários cenários de falha em sua aplicação.
Definindo Erros Customizados
enum ErroDeRede: Error {
case urlIncorreta
case semDados
case respostaInvalida
}
Lançando Erros
Você pode lançar erros de suas funções usando a palavra-chave throw
. Funções que podem lançar erros devem ser marcadas com a palavra-chave throws
.
func buscarDados(urlString: String) throws -> Data {
guard let url = URL(string: urlString) else {
throw ErroDeRede.urlIncorreta
}
let dados = Data() // Simular busca de dados
guard dados.count > 0 else {
throw ErroDeRede.semDados
}
return dados
}
Capturando Erros
Ao chamar uma função que lança erros, você usa um bloco do-catch
para tratar os erros potenciais.
do {
let dados = try buscarDados(urlString: "https://exemplo.com")
print("Dados buscados: \(dados)")
} catch ErroDeRede.urlIncorreta {
print("URL inválida.")
} catch ErroDeRede.semDados {
print("Nenhum dado retornado.")
} catch {
print("Erro inesperado: \(error).")
}
O Tipo Result
O tipo Result
é uma maneira poderosa de representar sucesso ou falha sem usar exceções. Ele encapsula um valor que pode ser um sucesso ou uma falha, resultando em um tratamento de erros mais claro e um código mais legível.
Definindo o Tipo Result
O tipo Result
é um enum com dois casos: sucesso
e falha
. Ele pode armazenar um valor de sucesso ou um erro.
enum Result<Sucesso, Falha: Error> {
case sucesso(Sucesso)
case falha(Falha)
}
Usando Result com Operações Assíncronas
O tipo Result
é especialmente útil para operações assíncronas, onde você pode lidar com sucesso e falha dentro de closures.
func buscarDadosAsync(urlString: String, completion: @escaping (Result<Data, ErroDeRede>) -> Void) {
DispatchQueue.global().async {
do {
let dados = try buscarDados(urlString: urlString)
completion(.sucesso(dados))
} catch let erro as ErroDeRede {
completion(.falha(erro))
} catch {
completion(.falha(.respostaInvalida))
}
}
}
Tratando o Resultado em um Manipulador de Conclusão
Ao usar a função acima, você pode tratar seu resultado facilmente.
buscarDadosAsync(urlString: "https://exemplo.com") { resultado in
switch resultado {
case .sucesso(let dados):
print("Dados buscados com sucesso: \(dados)")
case .falha(let erro):
print("Ocorreu um erro: \(erro)")
}
}
Combine Tratamento de Erros com Tipos de Resultado
Usando o tipo Result
do Swift, você pode encadear múltiplas operações assíncronas enquanto mantém o tratamento de erros limpo e direto.
Encadeando Chamadas Assíncronas
func buscarPerfilUsuario(urlString: String, completion: @escaping (Result<PerfilUsuario, ErroDeRede>) -> Void) {
buscarDadosAsync(urlString: urlString) { resultado in
switch resultado {
case .sucesso(let dados):
// Assumindo que parsePerfilUsuario é uma função que converte Data em PerfilUsuario
if let perfilUsuario = parsePerfilUsuario(dados) {
completion(.sucesso(perfilUsuario))
} else {
completion(.falha(.respostaInvalida))
}
case .falha(let erro):
completion(.falha(erro))
}
}
}
Conclusão
Nesta aula, examinamos o tratamento avançado de erros em Swift usando tipos de erro personalizados e o tipo Result
. Ao estruturar nossos erros e usar Result
de maneira eficaz, possibilitamos um código mais limpo e mais fácil de manter, especialmente ao lidar com operações assíncronas. Essa abordagem não apenas melhora a legibilidade do código, mas também aprimora o mecanismo de tratamento de erros em suas aplicações Swift.
Experimente esses conceitos em seus próprios projetos para reforçar sua compreensão e melhorar suas habilidades de gerenciamento de erros. Boa codificação!