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
    }
}
相关推荐
小浣熊熊熊熊熊熊熊丶6 小时前
《Effective Java》第25条:限制源文件为单个顶级类
java·开发语言·effective java
啃火龙果的兔子6 小时前
JDK 安装配置
java·开发语言
星哥说事6 小时前
应用程序监控:Java 与 Web 应用的实践
java·开发语言
等....7 小时前
Miniconda使用
开发语言·python
zfj3217 小时前
go为什么设计成源码依赖,而不是二进制依赖
开发语言·后端·golang
醇氧7 小时前
org.jetbrains.annotations的@Nullable 学习
java·开发语言·学习·intellij-idea
Java&Develop7 小时前
Aes加密 GCM java
java·开发语言·python
weixin_462446237 小时前
使用 Go 实现 SSE 流式推送 + 打字机效果(模拟 Coze Chat)
开发语言·后端·golang
JIngJaneIL7 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
敲敲了个代码8 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web