Appearance
Swift 入门(14):错误处理
在 Swift 中,错误处理主要通过
throw/try/catch来实现。
和异常不同,Swift 错误必须显式声明和处理,更安全。
1. 定义错误类型
Swift 的错误必须遵循 Error 协议。
swift
enum FileError: Error {
case notFound
case noPermission
}2. 抛出错误
swift
func readFile(name: String) throws -> String {
if name == "secret.txt" {
throw FileError.noPermission
}
return "文件内容"
}3. 捕获错误
swift
do {
let content = try readFile(name: "secret.txt")
print(content)
} catch FileError.notFound {
print("❌ 文件未找到")
} catch FileError.noPermission {
print("⛔ 没有权限")
} catch {
print("⚠️ 其它错误:\(error)")
}4. try? 和 try!
try?:错误时返回nil。try!:确定不会出错时使用,出错会崩溃。
swift
let result1 = try? readFile(name: "a.txt") // Optional("文件内容")
let result2 = try? readFile(name: "secret.txt") // nil
let result3 = try! readFile(name: "a.txt") // 强制执行5. defer(清理资源)
defer 块中的代码在函数结束时执行,常用于释放资源。
swift
func processFile() throws {
print("开始处理文件")
defer {
print("关闭文件")
}
throw FileError.notFound
}
try? processFile()
// 输出:
// 开始处理文件
// 关闭文件defer 的实战应用:回调清理
swift
// 系统 API 回调中的资源清理
public func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
defer {
self.callback = nil // 确保函数退出前清理回调
}
self.callback?(self.toJSON(["ok": false, "errMsg": error.localizedDescription]))
}defer 的执行时机
swift
func demonstrateDefer() {
print("1. 函数开始")
defer {
print("4. defer 块执行")
}
print("2. 中间逻辑")
if someCondition {
print("3a. 提前返回")
return // defer 仍会执行
}
print("3b. 正常结束")
// defer 在这里执行
}
// 输出(提前返回情况):
// 1. 函数开始
// 2. 中间逻辑
// 3a. 提前返回
// 4. defer 块执行多个 defer 的执行顺序
swift
func multipleDefer() {
defer { print("第一个 defer") }
defer { print("第二个 defer") }
defer { print("第三个 defer") }
print("函数主体")
}
multipleDefer()
// 输出(后进先出 LIFO):
// 函数主体
// 第三个 defer
// 第二个 defer
// 第一个 deferdefer 的实际应用场景
swift
// 1. 文件操作清理
func readFileWithCleanup(_ path: String) -> String? {
let file = openFile(path)
defer {
closeFile(file) // 确保文件被关闭
}
guard file.isValid else { return nil }
return file.readContent()
}
// 2. 网络请求状态管理
func performNetworkRequest() {
isLoading = true
defer {
isLoading = false // 确保加载状态被重置
}
// 网络请求逻辑
if requestFailed {
return // defer 仍会执行,isLoading 会被设为 false
}
processResponse()
}
// 3. 数据库事务管理
func updateDatabase() throws {
let transaction = database.beginTransaction()
defer {
if transaction.isActive {
transaction.rollback() // 确保事务被回滚或提交
}
}
try database.insert(record1)
try database.insert(record2)
transaction.commit()
}
// 4. 认证回调清理(你的代码)
class AuthManager {
private var callback: ((String) -> Void)?
func authenticate(_ options: String, _ cb: @escaping (String) -> Void) {
self.callback = cb
// 执行认证...
}
// 成功回调
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
defer {
self.callback = nil // 确保回调被清理
}
// 处理成功结果
let result = processAuthorization(authorization)
self.callback?(result)
}
// 失败回调(你的代码)
public func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
defer {
self.callback = nil // 无论如何都清理回调
}
self.callback?(self.toJSON(["ok": false, "errMsg": error.localizedDescription]))
}
}defer vs 普通清理的对比
swift
// ❌ 容易遗漏清理的写法
func badCleanupExample() {
self.callback = someCallback
if condition1 {
self.callback = nil // 需要手动清理
return
}
if condition2 {
// 忘记清理 callback!
return
}
doSomething()
self.callback = nil // 需要手动清理
}
// ✅ 使用 defer 确保清理
func goodCleanupExample() {
defer {
self.callback = nil // 自动清理,不会遗漏
}
self.callback = someCallback
if condition1 {
return // defer 自动执行
}
if condition2 {
return // defer 自动执行
}
doSomething()
// defer 自动执行
}总结
- 用
enum+Error定义错误类型。 - 用
throw抛出,用try+catch捕获。 try?返回可选,try!强制执行。defer用于清理收尾。