Como fazer os erros falarem a língua do usuário?
\n\nDesenvolvedores Swift frequentemente enfrentam o problema: o erro é lançado, mas o usuário vê algo como Error Domain=MyApp Code=42. Isso é tecnicamente correto, mas absolutamente inútil para uma pessoa. No Stack Overflow, a pergunta "How to provide a localized description with an Error type in Swift?" acumulou milhares de visualizações — e não é à toa.
Neste artigo, vamos analisar como transformar códigos de erro secos em mensagens claras e localizadas. Você aprenderá a usar o protocolo LocalizedError, trabalhar com NSError e preparar corretamente strings para diferentes idiomas. Pronto para tornar seu aplicativo mais amigável? Vamos lá!
Por que apenas Error não funciona?
\n\nEm Swift, o protocolo Error é um contrato mínimo. Ele não exige descrição nem localização. Quando você cria seu próprio erro:
enum NetworkError: Error {\n case timeout\n case serverError(code: Int)\n}\n\n...você obtém apenas o nome do caso. Tente chamar localizedDescription:
let error = NetworkError.timeout\nprint(error.localizedDescription) // "The operation couldn’t be completed. (NetworkError error 0.)"\n\nO sistema insere uma frase padrão — pouco informativa e feia. Para dar ao usuário uma mensagem significativa, é necessário implementar o protocolo LocalizedError.
Conheça: o protocolo LocalizedError
\n\nLocalizedError estende Error e adiciona quatro propriedades opcionais:
- \n
errorDescription— mensagem principal para o usuário \n failureReason— motivo do erro (técnico) \n recoverySuggestion— o que o usuário deve fazer \n helpAnchor— link para ajuda (raramente usado) \n
O mais importante é errorDescription. É ele que os componentes do sistema (alertas, SwiftUI) exibem.
Implementando um erro localizado
\n\nVamos adicionar LocalizedError ao nosso NetworkError:
enum NetworkError: LocalizedError {\n case timeout\n case serverError(code: Int)\n case noInternet\n \n var errorDescription: String? {\n switch self {\n case .timeout:\n return NSLocalizedString(\n "O servidor não responde. Verifique a conexão e tente novamente.",\n comment: "Timeout error"\n )\n case .serverError(let code):\n let format = NSLocalizedString(\n "Erro do servidor: %d. Tente novamente mais tarde.",\n comment: "Server error with code"\n )\n return String(format: format, code)\n case .noInternet:\n return NSLocalizedString(\n "Sem conexão com a internet.",\n comment: "No internet error"\n )\n }\n }\n \n var failureReason: String? {\n switch self {\n case .timeout:\n return NSLocalizedString(\n "Tempo limite de resposta do servidor excedido.",\n comment: "Timeout reason"\n )\n case .serverError(let code):\n return NSLocalizedString(\n "O servidor retornou o código \\(code).",\n comment: "Server error reason"\n )\n case .noInternet:\n return NSLocalizedString(\n "Nenhuma conexão de internet ativa.",\n comment: "No internet reason"\n )\n }\n }\n \n var recoverySuggestion: String? {\n switch self {\n case .timeout:\n return NSLocalizedString(\n "Verifique o Wi-Fi ou os dados móveis e repita a solicitação.",\n comment: "Timeout recovery"\n )\n case .serverError:\n return NSLocal