加深理解代替单纯记忆
关于block的基本应用和底层认识,可参考《深入了解block》。
本次只想弄清楚,遇到嵌套closure时,关于weak self的写法总有些不确定问题
先看一个例子
let closure: ClosureType = { [weak self] in
let embeddedClosure: ClosureType = {
let newSelf = self
}
embeddedClosure()
}
closure()
self.closure = closure
无内存泄漏(无循环引用)
- 说明closure是在最近的scope中找被捕获变量,即embeddedClosure找到的是weak self
再来
let closure: ClosureType = { [weak self] in
guard let self = self else { return }
let embeddedClosure: ClosureType = {
let newSelf = self
}
}
self.closure = closure
无泄漏
为什么无泄漏呢?按照上面理论,embeddedClosure中不应该捕获的是guard let self = self else { return }这句产生的strong self么?
对,上面的理论没有问题。问题在于,closure根本没有执行,所以embeddedClosure根本没有机会初始化,也就不存在捕获self的问题了
- 捕获变量行为发生在closure初始化阶段
那好,我们按照上面的说法修改正确,如下所示
let closure: ClosureType = { [weak self] in
guard let self = self else { return }
let embeddedClosure: ClosureType = {
let newSelf = self
}
}
closure()
self.closure = closure
结果仍然是--无泄漏
embeddedClosure确实初始化了,也捕获了strong的self。哪里出了问题?回想一下经典的循环引用范式self->block->self,我们也写一下该例子中的引用关系
self -> closure - - -> weak self虚线表示弱引用embeddedClosure -> self
此时有人(就是我)会觉得,不对啊,closure对embeddedClosure不也应该有强引用么?
该例中,embeddedClosure只是closure中的一个局部变量,closure根本没有捕获embeddedClosure,所以也就不存在任何引用了
最后
var embeddedClosure: ClosureType?
let closure: ClosureType = { [weak self] in
guard let self = self else { return }
embeddedClosure = {
let newSelf = self
}
}
closure()
self.closure = closure
终于内存泄漏了
self -> closure -> embeddedClosure -> self
总了个结
- closure是在最近的scope中找被捕获变量
- 捕获变量行为发生在closure初始化阶段