编程iOS 开发员

描述 Swift 中错误处理 (Error Handling) 的工作原理。错误有哪些类型,有哪些处理方式,何时更倾向于使用 throw/catch,何时使用 Result?

用 Hintsage AI 助手通过面试

答复。

Swift 通过 Error 协议和 throwtrycatch 语法支持严格的错误处理系统。您可以通过继承 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 类型。最终应用程序以不同方式处理相同类型的故障,用户界面为同一错误显示不同消息——难以维护和测试。