Esk*_*918 8 closures retain-cycle swift
我只是想知道我是否正确理解这一点.因此,根据apple docs,当你创建一个闭包作为类实例的属性并且该闭包引用self(创建闭包属性的类)时,这将导致一个强大的保留周期,最终类和闭包将被释放.所以在非专业术语中,这意味着如果我有一个具有属性且该属性是闭包的类,并且一旦我在类中分配了该闭包的功能,该类声明了将导致强保留周期的闭包属性.下面简要说明我的意思
class SomeViewController{
let myClosure:()->Void
public func someFunction(){
....bunch of code
myClosure = {
self.dismiss(blahBlahBlah)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这最终会导致保留循环,因为闭包保持对self的强引用,self是创建闭包属性的类.现在根据苹果来解决这个问题,我会定义一个类似的捕获列表
class SomeViewController{
let myClosure:()->Void
public func someFunction(){
....bunch of code
myClosure = { [weak self] in
self?.dismiss(blahBlahBlah)
}
}
}
Run Code Online (Sandbox Code Playgroud)
注意我如何在in语句之前放置[weak self].这使得闭包只知道对自身的弱引用而不是强引用.当封闭和自我生存相同的持续时间时,IM应该使用弱的时候自我可以关闭或无主.
我从这里获得此信息自动引用计数和该链接的强引用循环部分,这句话"如果你为一个类实例的属性分配一个闭包,那么一个强引用循环也会出现那个闭包抓住了实例"我大约90%确定我正确地理解了这一点,但只有10%的怀疑.所以我有这个正确吗?
我之所以这样问是因为我在视图中使用了一些回调函数.那些回调调用自己,但那个场景中的self是响应回调而不是实际视图本身的视图控制器.这就是我自己怀疑的地方,因为我从那句话突出显示我不认为我需要把[weak self]所有那些按钮回调,但我只是确定.这是一个例子
class SomeViewController {
let someSubview:UIView
override viewDidLoad() {
//Some Subview has a button and in that view I just have some action that gets fired off calling the callback here in the view controller I don't need to use the [weak self] in this scenario because closure property is not in this class correct?
someSubview.someButtonsCallback = {
....run code then
self?.dismiss(blahBlahBlah)
}
}
Run Code Online (Sandbox Code Playgroud)
是的,这仍然会导致保留周期.
最简单的保留周期是2个对象,每个对象都具有相互较强的引用,但也可以使用3向和更大的保留周期.
在您的情况下,您有视图控制器谁的视图包含一个按钮(强引用.)该按钮具有对闭包的强引用.闭包强烈引用使用self的视图控制器.所以视图拥有按钮.按钮拥有关闭.该闭包拥有视图控制器.如果你关闭视图控制器(说它是一个模态),那么它应该被解除分配.但是,由于您具有此3向保留周期,因此不会取消分配.您应该使用print语句向视图控制器添加一个deinit方法并尝试它.
解决方案是添加捕获列表([weak self]位),就像在第一个示例中一样.
请注意,常见的模式是添加捕获列表,然后将弱变量映射到闭包内的强变量:
let myClosure = { [weak self] in
guard let strongSelf = self else { return }
//...
strongSelf.doSomething()
}
Run Code Online (Sandbox Code Playgroud)
这样,如果闭包仍处于活动状态,但拥有它的对象被释放,则开头的guard语句检测到self为nil并在闭包开始时退出.否则,每次引用时都必须打开可选项.
在某些情况下,它也有可能是在捕获列表(在这些例子中个体经营)的对象可以在封闭的正在执行中,这可能会导致不可预测的行为被释放.(Gory详细信息:只有当闭包运行在与捕获列表中对象的所有者不同的线程上时才会运行,但是完成处理程序通常在后台线程上运行,所以它确实发生了)
想象一下:
let myClosure = { [weak self] in
self?.step1() //1
//time-consuming code
self?.property = newValue //2
//more time-consuming code
self?.doSomething() //3
//even more time-consuming code
self?.doSomethingElse() //4
}
Run Code Online (Sandbox Code Playgroud)
通过上面的代码,如果是关闭后台线程上运行,它可能是自仍然会在步骤1有效的,但你的时间执行步骤2,自我已释放.步骤3和4也是如此.通过guard strongSelf = self else { return }在闭包的开头添加,你可以在闭包的入口处测试,以确保self仍然有效,如果是,则使闭包创建一个只有生命的强引用只要闭包运行,并且self在闭包代码执行时防止被释放.)
| 归档时间: |
|
| 查看次数: |
2560 次 |
| 最近记录: |