Swift闭包的本质

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

2 捕获值:闭包会捕获上下文使用到的变量(引用类型会保持引用关系),如果没有显式捕获列表, swift会默认按值捕获局部变量或对引用类型捕获强引用。为了避免强引用循环,可以通过[weak self]或[unowned 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
    }
}
相关推荐
云边小网安33 分钟前
分析 java 的 Map<String,Map<String, List<Map<String,Integer>>>>
java·开发语言·list
fashia36 分钟前
Java转Go日记(六十二):Raft
开发语言·后端·golang·go
MessiGo7 小时前
Javascript 编程基础(5)面向对象 | 5.2、原型系统
开发语言·javascript·原型模式
慢半拍iii8 小时前
数据结构——D/串
c语言·开发语言·数据结构·c++
爱学习的白杨树9 小时前
Sentinel介绍
java·开发语言
Frankabcdefgh9 小时前
Python基础数据类型与运算符全面解析
开发语言·数据结构·python·面试
kaiaaaa9 小时前
算法训练第十五天
开发语言·python·算法
南玖i10 小时前
vue3 + ant 实现 tree默认展开,筛选对应数据打开,简单~直接cv
开发语言·前端·javascript
南枝异客10 小时前
三数之和-力扣
开发语言·javascript·数据结构·算法·leetcode·排序算法
爱意随风起风止意难平10 小时前
AIGC 基础篇 Python基础 05 元组,集合与字典
开发语言·python·aigc