defer关键字

目录

defer 是 Swift 语言中的一个重要关键字,用于声明一个代码块在当前作用域退出前执行,无论作用域是通过正常流程结束还是因错误提前退出。它的主要用途是确保清理工作(如资源释放、状态恢复等)始终被执行。

一、核心特性

  1. 延迟执行
swift 复制代码
func example() {
    print("步骤1")
    defer { print("清理操作") } // 最后执行
    print("步骤2")
}
// 输出:
// 步骤1
// 步骤2
// 清理操作
  1. 逆序执行(多个 defer 时):
swift 复制代码
func multiDefer() {
    defer { print("第一个defer") }
    defer { print("第二个defer") }
    print("函数主体")
}
// 输出:
// 函数主体
// 第二个defer
// 第一个defer
  1. 作用域绑定
swift 复制代码
if condition {
    defer { print("条件块内的defer") }
    // ...
}
// defer 在 if 块结束时执行

二、主要应用场景

2.1. 资源清理(最常用)

swift 复制代码
func readFile() {
    let file = openFile("data.txt")
    defer {
        closeFile(file) // 确保文件一定会关闭
        print("文件已关闭")
    }
    
    // 可能抛出错误或提前返回
    try processFile(file)
}

2.2. 锁管理

swift 复制代码
func threadSafeOperation() {
    lock.lock()
    defer { lock.unlock() } // 确保锁一定会释放
    
    // 临界区操作
    sharedResource.modify()
}

2.3. 错误处理

swift 复制代码
func riskyOperation() throws {
    let resource = acquireResource()
    defer { releaseResource(resource) } // 成功失败都会释放
    
    try mayThrowError()
    try anotherRiskyCall()
}

2.4. 状态恢复

swift 复制代码
func updateUI() {
    let originalColor = view.backgroundColor
    defer { view.backgroundColor = originalColor } // 恢复原始状态
    
    // 临时改变UI
    view.backgroundColor = .yellow
    performAnimation()
}

三、执行时机示例

swift 复制代码
func deferTiming() -> String {
    defer { print("defer 执行") }
    
    if true {
        print("返回前")
        return "返回值"
    }
}
/* 输出:
   返回前
   defer 执行
*/

四、注意事项

  1. 作用域规则
swift 复制代码
func scopeExample() {
    do {
        defer { print("内部defer") }
    }
    print("外部")
    defer { print("外部defer") } // 最后执行
}
// 输出:内部defer → 外部 → 外部defer
  1. 返回值影响
swift 复制代码
func returnExample() -> Int {
    var value = 10
    defer { value = 20 } // 不会改变返回值
    return value
}
print(returnExample()) // 输出 10
  1. 循环中的 defer
swift 复制代码
for i in 1...3 {
    defer { print("循环结束: \(i)") }
    print("循环开始: \(i)")
}
/* 输出:
   循环开始: 1
   循环结束: 1
   循环开始: 2
   循环结束: 2
   循环开始: 3
   循环结束: 3
*/
  1. 避免在 defer 中抛错
swift 复制代码
func dangerousDefer() throws {
    defer {
        // 避免在此抛出新错误,会覆盖原始错误
    }
    try somethingRisky()
}

五、与其它语言对比

特性 Swift (defer) Java (try-with-resources) Python (with)
资源自动释放
错误处理集成
可用于任意作用域
多个清理操作 ✅ (逆序)
修改返回值

六、最佳实践

  1. 保持 defer 块简短
swift 复制代码
// ✅ 推荐
defer { cleanup() }

// ❌ 避免
defer {
    step1()
    step2()
    // 复杂逻辑
}
  1. 处理依赖关系
swift 复制代码
func resourceHandling() {
    let res1 = acquireA()
    defer { releaseA(res1) }
    
    // res2 依赖 res1
    let res2 = acquireB(res1)
    defer { releaseB(res2) } // 后申请的先释放
}

3.配合 do-catch

swift 复制代码
func loadData() {
    do {
        let data = try fetchData()
        defer { cleanup() } // 成功和失败都会执行
        process(data)
    } catch {
        handleError(error)
    }
}

defer 是 Swift 中实现"资源获取即初始化"(RAII)模式的关键工具,它能显著提高代码的安全性和可读性,特别是在涉及资源管理和错误处理的场景中。

相关推荐
大熊猫侯佩3 天前
WWDC 25 风云再起:SwiftUI 7 Charts 心法从 2D 到 3D 的华丽蜕变
swiftui·swift·wwdc
大熊猫侯佩4 天前
Swift 6.2 并发江湖:两大神功破局旧制,代码运行经脉革新(下)
swiftui·swift·wwdc
大熊猫侯佩4 天前
Swift 6.2 并发江湖:两大神功破局旧制,代码运行经脉革新(上)
swiftui·swift·wwdc
大熊猫侯佩4 天前
SwiftUI 7 江湖新风:WWDC25 揭晓神秘武林志
swiftui·swift·wwdc
大熊猫侯佩4 天前
SwiftUI 7(iOS 26 / iPadOS 26)中玻璃化标签页的全新玩法
swiftui·swift·apple
Daniel_Coder4 天前
iOS Widget 开发-1:什么是 iOS Widget?开发前的基本认知
ios·swiftui·swift·widget
小弟调调5 天前
Vidwall: 支持将 4K 视频设置为动态桌面壁纸,兼容 MP4 和 MOV 格式
macos·swiftui·桌面应用·macos app
帅次5 天前
【iOS设计模式】深入理解MVC架构 - 重构你的第一个App
ios·swiftui·objective-c·iphone·swift·safari·cocoapods