Swift中的错误处理:try/catch、throws和do-catch块

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

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

开始课程

Swift 中的错误处理:try/catch 及其他



iOS 和 macOS 开发需要可靠的错误管理。Swift 提供了一种强大而优雅的故障处理机制,基于关键字 throws、try、catch 和 do。在本文中,我们将分析如何正确处理错误、编写可读代码并避免常见陷阱。



1. 基础:Error 协议和 throws 关键字



Swift 中的任何错误都必须符合 Error 协议。通常使用枚举 (enum) 来实现:



enum NetworkError: Error {    case badURL    case noData    case decodingFailed(String)}


可能抛出错误的函数使用关键字 throws 标记:



func fetchUser(from urlString: String) throws -> User {    guard let url = URL(string: urlString) else {        throw NetworkError.badURL    }    // ... 请求逻辑}


现在,当调用此类函数时,编译器将强制您处理可能的错误。



2. do-catch 结构:错误捕获



最常见的处理方式是 do-catch 块。您将潜在的危险代码放在 do 中,并在 catch 中处理故障:



do {    let user = try fetchUser(from: "https://api.example.com/user")    print("User loaded: \\(user.name)")} catch NetworkError.badURL {    print("无效的 URL")} catch NetworkError.noData {    print("服务器未返回数据")} catch NetworkError.decodingFailed(let message) {    print("解码错误:\\(message)")} catch {    print("未知错误:\\(error.localizedDescription)")}


重要提示:最后一个没有指定具体类型的 catch 块会捕获所有剩余错误——建议始终添加它。



2.1. catch 中的模式匹配



您可以使用更复杂的条件:



do {    let result = try riskyOperation()} catch let error as NetworkError where error == .badURL {    print("URL 出现问题")} catch {    print(error)}


3. 替代方案:try? 和 try!



并非总是需要完整的处理。Swift 提供了两种简化的方法:



3.1. try? — 可选值



如果错误不严重,可以将结果转换为可选类型。发生故障时,函数将返回 nil:



let user = try? fetchUser(from: "https://example.com/user")// user 的类型是 User? — 出错时为 nil


非常适合可以忽略错误的情况(例如,加载头像)。



3.2. try! — 强制执行



仅在您绝对确定不会出错时使用 try!。否则——应用程序会崩溃:



let user = try! fetchUser(from: "https://valid-url.com/user")// 如果 URL 无效——应用程序将崩溃


在测试中或在程序逻辑上不可能发生故障的情况下使用 try!。



4. 高级技术:rethrows 和 deferred



4.1. 用于高阶函数的 rethrows



如果您的函数接受一个可能抛出错误的闭包,请使用 rethrows。如果闭包不抛出错误,这允许您不将自己的函数标记为 throws:



func process(_ closure: () throws -> Void) rethrows {    try closure()}

// 使用非 throws 闭包调用——不需要 do-catchprocess { print("没有错误") }

// 使用 throws 闭包调用——需要处理try process { throw NetworkError.noData }


4.2. deferred:保证的清理



defer 块在函数结束(成功或错误)时执行。非常适合关闭文件或释放资源。

博客

书籍推荐