使用 Swift 开发应用时,你可能遇到过这样的情况:用 do-catch 捕获了错误,却发现真正显示在屏幕上的消息并不理想。
如果直接使用 error.localizedDescription,用户很容易看到 “The operation couldn’t be completed…” 之类令人费解的文字。
先说结论。
在 Swift 中定义显示给用户的自定义错误消息时,应采用
LocalizedError协议,而不是Error,并实现errorDescription属性。
今天我们会结合示例,逐步讲解这种方法。
为什么只使用 Error 不够?
很多人会这样定义错误。
enum LoginError: Error {
case invalidPassword
case userNotFound
}
如果只做到这里就输出 error.localizedDescription,显示的将不是我们期待的“密码错误”,而是系统生成的平淡默认消息。
这是因为 Error 协议本身没有定义人类可读消息的位置。
这就是 LocalizedError 的用武之地。
如何定义 Swift 自定义错误消息?
方法很简单:采用 LocalizedError,并实现 errorDescription。
下面是为登录错误添加用户提示消息的示例。
extension LoginError: LocalizedError {
var errorDescription: String? {
switch self {
case .invalidPassword:
return "密码不正确."
case .userNotFound:
return "用户不存在."
}
}
}
现在调用 error.localizedDescription 时,就会原样显示我们定义的消息。
重点在于,errorDescription 的返回类型是 String?,也就是可选类型。
如果在这里返回 nil,就会再次回到系统默认消息。因此,为每个 case 提供值非常重要。
除了 errorDescription,还有其他选项吗?(failureReason · recoverySuggestion)
有。LocalizedError 还包含其他可以选择实现的属性。
它们的作用可以整理成下面这张表。
| 属性 | 作用 | 示例消息 |
|---|---|---|
errorDescription |
出了什么问题 | “登录失败。” |
failureReason |
为什么发生 | “密码已输错 5 次。” |
recoverySuggestion |
如何解决 | “请稍后重试。” |
尤其是 recoverySuggestion,在引导用户进行下一步操作时非常有用。
实际上,在 SwiftUI 的 Alert 或 AppKit 环境中,这些值甚至可以被自动读取并显示在屏幕上。
对于面向用户的错误,我通常至少会准备 errorDescription 和 recoverySuggestion。
不要混淆开发日志和用户消息
最后再补充一点。
想记录在调试日志中的开发者说明,建议使用 CustomStringConvertible(也就是 description),
而显示给用户的翻译后消息则放在 LocalizedError 中。
因为两者的目的不同:一个是为我自己准备的,另一个是为用户准备的。
这样分离职责后,日后支持多语言时,添加 NSLocalizedString 也会容易得多。
用一句话总结今天的内容:“如果错误要显示给用户,就先填好 LocalizedError 的 errorDescription。”
一个小习惯就能显著改善用户体验,所以请务必在下一个项目中试试看。加油!🙌
参考资料
- Create A Custom Swift Error [and override localizedDescription]
- Defining Custom Errors With Advanced Descriptions In Swift – SerialCoder.dev
- Alert and LocalizedError in SwiftUI – Augmented Code

