是的,那仍然会导致保留周期。
最简单的保留周期是2个对象,每个对象相互之间都有很强的引用,但是3向和更大的保留周期也是可能的。
在您的情况下,您的视图控制器的视图包含一个按钮(强引用)。该按钮具有对闭包的强引用。闭包使用self强烈引用视图控制器。因此,视图拥有该按钮。该按钮拥有闭包。该闭包拥有视图控制器。如果您关闭视图控制器(例如它是模式控制器),则应该将其释放。但是,由于您具有此3向保留周期,因此不会取消分配它。您应该使用打印语句将deinit方法添加到视图控制器,然后尝试使用它。
解决方案是
[weak self]像在第一个示例中那样添加捕获列表(该位)。
请注意,常见的模式是添加捕获列表,然后将弱变量映射到闭包内部的强变量:
let myClosure = { [weak self] in guard let strongSelf = self else { return } //... strongSelf.doSomething()}
这样,如果闭包仍处于活动状态,但拥有它的对象已被释放,则开始时的guard语句会检测到self为nil,并在闭包的开头退出。否则,每次引用可选项时都必须将其拆开。
在某些情况下,捕获列表中的对象(在这些示例中为self)也有可能被释放到正在执行的闭包的中间,这可能导致无法预测的行为。(详细信息:仅当闭包在与捕获列表中对象的所有者不同的线程上运行时,但完成处理程序通常在后台线程上运行,因此确实发生)
想象一下:
let myClosure = { [weak self] in self?.step1() //1 //time-consuming pre self?.property = newValue //2 //more time-consuming pre self?.doSomething() //3 //even more time-consuming pre self?.doSomethingElse() //4}
使用上面的代码,如果闭包在后台线程上运行,则可能在第1步中self仍然有效,但是到您执行第2步时,self已被释放。步骤3和步骤4也是如此。通过
guardstrongSelf = self else { return}在闭包的开头添加,您可以在闭包的入口处进行测试以确保self仍然有效,如果是,则使闭包创建一个仅能生存的强引用。只要闭包需要运行,并且可以防止
self在执行闭包代码时将其释放。)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)