Swift中的错误本地化:如何让Error对用户友好

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何让错误说用户的语言?

\n\n

Swift开发者经常遇到一个问题:错误被抛出,但用户看到的是类似 Error Domain=MyApp Code=42 这样的信息。这在技术上是正确的,但对人来说完全无用。在Stack Overflow上,问题 "How to provide a localized description with an Error type in Swift?" 获得了数千次浏览——这并非偶然。

\n\n

在本文中,我们将探讨如何将枯燥的错误代码转化为清晰、本地化的消息。您将了解如何使用 LocalizedError 协议、处理 NSError 以及如何正确准备不同语言的字符串。准备好让您的应用更友好了吗?让我们开始吧!

\n\n

为什么单纯的Error不起作用?

\n\n

在Swift中,Error 协议是一个最小契约。它既不要求描述,也不要求本地化。当您创建自己的错误时:

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

...您只会得到case的名称。尝试调用 localizedDescription:

\n\n
let error = NetworkError.timeout\nprint(error.localizedDescription) // "The operation couldn’t be completed. (NetworkError error 0.)"
\n\n

系统会替换成标准短语——信息不足且不美观。为了给用户提供有意义的消息,您需要实现 LocalizedError 协议。

\n\n

认识一下:LocalizedError协议

\n\n

LocalizedError 扩展了 Error,并添加了四个可选属性:

\n\n
    \n
  • errorDescription — 给用户的主要消息
  • \n
  • failureReason — 错误原因(技术性)
  • \n
  • recoverySuggestion — 用户应该怎么做
  • \n
  • helpAnchor — 帮助链接(很少使用)
  • \n
\n\n

最重要的是 errorDescription。系统组件(警告框、SwiftUI)正是显示这个属性。

\n\n

实现本地化错误

\n\n

为我们的 NetworkError 添加 LocalizedError:

\n\n
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                "服务器无响应。请检查连接并重试。",\n                comment: "Timeout error"\n            )\n        case .serverError(let code):\n            let format = NSLocalizedString(\n                "服务器错误:%d。请稍后重试。",\n                comment: "Server error with code"\n            )\n            return String(format: format, code)\n        case .noInternet:\n            return NSLocalizedString(\n                "没有互联网连接。",\n                comment: "No internet error"\n            )\n        }\n    }\n    \n    var failureReason: String? {\n        switch self {\n        case .timeout:\n            return NSLocalizedString(\n                "等待服务器响应超时。",\n                comment: "Timeout reason"\n            )\n        case .serverError(let code):\n            return NSLocalizedString(\n                "服务器返回了代码 \\(code)。",\n                comment: "Server error reason"\n            )\n        case .noInternet:\n            return NSLocalizedString(\n                "没有活跃的互联网连接。",\n                comment: "No internet reason"\n            )\n        }\n    }\n    \n    var recoverySuggestion: String? {\n        switch self {\n        case .timeout:\n            return NSLocalizedString(\n                "请检查Wi-Fi或移动数据,然后重试请求。",\n                comment: "Timeout recovery"\n            )\n        case .serverError:\n            return NSLocal                

博客

书籍推荐