在异步函数中处理清理逻辑时,defer
语句能确保代码在当前作用域退出前执行,无论函数是正常结束、抛出错误还是被提前返回。本文将通过一个常见场景------显示/隐藏加载指示器------演示 defer
的用法。
典型用例
swift
func fetch() async {
isLoading = true
defer { isLoading = false } // 清理逻辑集中在此
do {
articles = try await service.fetchArticles()
} catch {
self.error = error.localizedDescription
}
}
传统实现方式对比
- 多位置设置(易遗漏):
swift
isLoading = true
do {
...
isLoading = false
} catch {
...
isLoading = false
}
- 单次底部设置(无法应对提前退出):
swift
isLoading = true
do {
...
} catch {
...
}
isLoading = false // 若中途 return 或 await 取消,此行不会执行
defer 的优势
-
统一清理入口:将清理逻辑集中在一处,避免分散在各分支。
-
容错性:自动处理以下场景:
- 函数正常结束
- 抛出错误
- 提前返回(
return
) await
过程中被取消
适用场景扩展
- 资源释放:文件句柄、网络连接等
- UI 状态管理:进度条、禁用按钮等
- 并发安全 :配合
actor
防止竞态条件
总结
defer
是 Swift 中管理临时状态和资源的利器,尤其适合异步编程场景。通过将清理逻辑延迟到作用域结束时执行,它能显著提升代码的健壮性和可维护性,降低因流程分支复杂导致的遗漏风险。对于需要确保执行清理操作的场景(如加载状态、锁机制等),建议优先考虑使用 defer
。