Swift 中的闭包是什么?闭包的捕获列表是什么?什么是逃逸闭包和非逃逸闭包?
Swift 中的闭包是自包含的函数代码块,可以在代码中被传递和使用。闭包可以捕获和存储其所在上下文中任意常量和变量的引用。
闭包的基本概念:
- 闭包是引用类型
- 可以作为参数传递给函数
- 可以作为函数的返回值
- 可以存储在变量或常量中
- 三种形式:全局函数、嵌套函数、闭包表达式
闭包的语法:
swift// 完整形式 let greeting = { (name: String) -> String in return "Hello, \(name)" } // 简化形式 let greeting = { name in "Hello, \(name)" } // 最简形式(使用参数缩写) let greeting: (String) -> String = { "Hello, \($0)" }
捕获列表:
- 用于显式声明闭包要捕获的变量
- 使用
[weak self]或[unowned self]避免循环引用 - 使用
[weak var = weakVar]捕获弱引用 - 使用
[unowned var = var]捕获无主引用 - 示例:
swift
let closure = { [weak self] in self?.doSomething() }
逃逸闭包:
- 在函数返回后仍会被调用的闭包
- 使用
@escaping标记 - 必须显式引用
self - 常用于异步操作、回调、网络请求
- 示例:
swift
func request(completion: @escaping (Result) -> Void) { DispatchQueue.global().async { let result = fetchData() completion(result) } }
非逃逸闭包:
- 在函数返回前会被调用的闭包
- Swift 3.0+ 默认为非逃逸
- 可以隐式引用
self - 性能更好,编译器可以优化
- 示例:
swift
func process(_ closure: (Int) -> Void) { closure(42) }
最佳实践:
- 使用捕获列表避免循环引用
- 优先使用非逃逸闭包
- 合理使用尾随闭包语法
- 使用
weak或unowned处理 self 引用 - 考虑闭包的内存开销