Swift 中的错误处理:try/catch 及其他:从 A 到 Z

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

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

开始课程

Swift 中的错误处理:try/catch 及其他 — 完整指南



错误处理是 iOS 和 macOS 开发中的关键主题之一。Swift 语言实现了一套强大而优雅的故障管理系统,远远超出了简单的 try/catch。理解这些机制可以让你编写出可靠、可预测且安全的代码。在本文中,我们将剖析所有方面:从基本的错误声明到使用可选值和反初始化器的高级技术。



基础:Error 协议和 throws 关键字



在 Swift 中,任何错误都必须符合 Error 协议。通常使用枚举 (enum) 来实现这一点。让我们看一个简单的例子——密码验证:



enum PasswordError: Error {    case tooShort    case missingDigit    case missingUppercase}

func validatePassword(_ password: String) throws { guard password.count >= 8 else { throw PasswordError.tooShort } guard password.rangeOfCharacter(from: .decimalDigits) != nil else { throw PasswordError.missingDigit } guard password.rangeOfCharacter(from: .uppercaseLetters) != nil else { throw PasswordError.missingUppercase } print("密码正确")}


函数声明中的 throws 关键字告诉编译器,执行可能会被错误中断。调用此类函数需要特殊的语法。



do-catch 结构和 try 关键字



为了处理潜在的错误,使用带有 try 标记的 do-catch 块:



do {    try validatePassword("Hello123")    print("成功!")} catch PasswordError.tooShort {    print("错误:密码太短")} catch PasswordError.missingDigit {    print("错误:密码中没有数字")} catch PasswordError.missingUppercase {    print("错误:密码中没有大写字母")} catch {    print("未知错误:\\(error)")}


请注意最后一个 catch 块——它捕获任何之前未处理到的错误。这是一个强制性要求:Swift 编译器会检查所有可能的错误是否都已处理。



try? 和 try! — 简化的错误处理方式



有时你不需要对错误进行完全控制。Swift 提供了两种简写形式:



  • try? — 将错误转换为可选值 nil。如果没有错误,则返回包装在 Optional 中的结果。
  • try! — 断言不会发生错误。如果错误确实发生,应用程序将崩溃(运行时崩溃)。


// try? — 安全地忽略错误if let _ = try? validatePassword("weak") {    print("密码验证通过")} else {    print("密码未通过")}

// try! — 仅当你 100% 确定时使用let result = try! validatePassword("StrongPass1") // 如果密码无效则崩溃


仅在理论上不可能出错的情况下使用 try!(例如,加载应用程序捆绑包中的资源时)。



高级技术:rethrows、defer 和 Result



重新抛出错误 (rethrows)



rethrows 关键字应用于高阶函数,这些函数接受可能抛出错误的闭包。函数本身不抛出错误,但传递来自闭包的错误:



func processItems(_ items: [String], using validator: (String) throws -> Void) rethrows {    for item in items {        try validator(item)    }}

// 使用do { try processItems(["Hello", "World123"], using: validatePassword)} catch { print("处理错误:\\(error)")}


这允许编写灵活的包装函数,而无需重复错误处理代码。



博客

书籍推荐