快速闭合导致自我强烈的保留周期

快速闭合导致自我强烈的保留周期,第1张

快速闭合导致自我强烈的保留周期

是的,那仍然会导致保留周期。

最简单的保留周期是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
在执行闭包代码时将其释放。)



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5029030.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-15
下一篇 2022-11-15

发表评论

登录后才能评论

评论列表(0条)

保存