Swift 通过 Error 协议和 throw、try、catch 语法支持严格的错误处理系统。您可以通过继承 Error 定义自己的错误类型:
enum NetworkError: Error { case noInternet case serverError(code: Int) case unknown }
可能引发错误的函数会使用 throws 声明:
func fetchData() throws -> Data { // ... throw NetworkError.noInternet }
可以使用 do-catch 块处理错误:
do { let data = try fetchData() // 处理数据 } catch NetworkError.noInternet { print("没有互联网") } catch { print("其他错误: \(error)") }
另一种方法是 Result<T, Error> 类型,允许在不需要 try-catch 的情况下返回结果或错误:
func fetchData() -> Result<Data, NetworkError> { // ... return .failure(.noInternet) } let result = fetchData() switch result { case .success(let data): // OK case .failure(let err): // 处理错误 }
何时使用:
try/catch。Result。问题:“是否可以抛出和捕获任何类型的错误,例如字符串或数字?”
**回答:**不,在 Swift 中只能抛出符合 Error 协议的类型。
// 错误: throw "StringError" // 编译器不允许这样做 // 正确: struct MyError: Error {} throw MyError()
故事
在 REST API 客户端项目中,抛出一个字符串错误 (throw "No data")。代码在 JavaScript 中编译,但转换为 Swift 后出现致命编译错误。
故事
开发人员通过可选值返回错误(在错误时 return nil),而不是通过 throw/Result。结果丢失了错误的细节,难以正确处理——因此发生了静默失败。
故事
分析显示,在应用程序中的几个地方,相同的错误没有归类为一个 Error 类型。最终应用程序以不同方式处理相同类型的故障,用户界面为同一错误显示不同消息——难以维护和测试。