Swift闭包的本质

1 闭包的本质其实是一个引用类型:存储在堆空间上,由堆分配空间,且生命周期由ARC(自动引用计数机制)管理

2 捕获值:闭包会捕获上下文使用到的变量(引用类型会保持引用关系),如果没有显式捕获列表, swift会默认按值捕获局部变量或对引用类型捕获强引用。为了避免强引用循环,可以通过weak selfunowned self来避免。如下所示

复制代码
class Counter {
    var total = 0

    func makeIncrementer() -> () -> Int {
        return { [unowned self] in
            self.total += 1
            return self.total
        }
    }
}

let counter = Counter()
let incrementer = counter.makeIncrementer()
print(incrementer()) // 输出: 1
print(incrementer()) // 输出: 2
print(counter.total) // 输出: 2

3 延迟执行

闭包中的代码只有在闭包被调用时才会执行,适合回调和异步任务。

复制代码
let greeting: () -> Void = {
    print("Hello, Swift!")
}

print("Before calling the closure")
greeting() // 闭包被调用,这里的代码才会执行
print("After calling the closure")


输出
Before calling the closure
Hello, Swift!
After calling the closure

闭包延迟执行在事件处理中的应用,举例:比如我要给网络发送一条请求,得到数据来更新我的UI视图,但是网络的响应时间我们是不确定的,所以就会导致更新UI的时机并不确定。我们就可以借助逃逸闭包@escaping来解决这个问题,@escaping 用于标记闭包参数,表示这个闭包可能会在函数返回后被异步调用。闭包会在函数作用域之外执行,而不是在函数调用时立即执行,然后在闭包中执行更新逻辑。如下面的例子,我们在闭包中更新answer就可以解决该问题了。

Swift 复制代码
func chatRequest(inputId : String,input : String,completion:@escaping(String) -> Void) {
     //completion会异步自动调用
     completion(String)
}


if let question = questions{
    request?.chatRequest(inputId:inputID,input: question){[weak self] answer in
        self?.answer = answer
    }
}
相关推荐
小白学大数据1 分钟前
爬虫性能天花板:asyncio赋能 Aiohttp,并发提速 10 倍
开发语言·爬虫·数据分析
凡人叶枫12 分钟前
Effective C++ 条款07:为多态基类声明 virtual 析构函数
linux·c语言·开发语言·c++
iOS开发上架哦15 分钟前
Jenkins 自动上传 IPA 到 App Store 把发布步骤融入 CI/CD
后端·ios
凡人叶枫21 分钟前
Effective C++ 条款10:令 operator= 返回一个 reference to *this
java·linux·服务器·开发语言·c++·effective c++
leo__5201 小时前
MATLAB实现牧羊人算法
开发语言·算法·matlab
格发许可优化管理系统1 小时前
Mentor许可证使用规定全解析
java·大数据·c语言·开发语言·c++
ZJPRENO1 小时前
2026 苹果 WWDC 完整总结
ios
FL16238631291 小时前
C# OpenCvSharp 基于霍夫变换直线检测的文本图像倾斜校正文本图像倾斜校
开发语言·c#
techdashen1 小时前
在 Fly.io 上使用 Rust 构建远程开发环境:从 Tokio 到 eBPF
开发语言·后端·rust
留白_2 小时前
pandas文件读取与存储
开发语言·python·pandas