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
    }
}
相关推荐
四维碎片2 小时前
【Qt】线程池与全局信号实现异步协作
开发语言·qt·ui·visual studio
IT码农-爱吃辣条2 小时前
Three.js 初级教程大全
开发语言·javascript·three.js
☺����3 小时前
实现自己的AI视频监控系统-第一章-视频拉流与解码2
开发语言·人工智能·python·音视频
染翰3 小时前
lua入门以及在Redis中的应用
开发语言·redis·lua
王者鳜錸3 小时前
PYTHON让繁琐的工作自动化-函数
开发语言·python·自动化
兔老大RabbitMQ4 小时前
git pull origin master失败
java·开发语言·git
tt5555555555554 小时前
C/C++嵌入式笔试核心考点精解
c语言·开发语言·c++
xiao助阵4 小时前
python实现梅尔频率倒谱系数(MFCC) 除了傅里叶变换和离散余弦变换
开发语言·python
HarderCoder4 小时前
我们真的需要 typealias 吗?——一次 Swift 抽象成本的深度剖析
swift
科大饭桶4 小时前
C++入门自学Day14-- Stack和Queue的自实现(适配器)
c语言·开发语言·数据结构·c++·容器