简体   繁体   English

这些闭包中的保留周期有什么区别? 标准闭包与对象初始化闭包

[英]What is the difference between retain cycle in these closures? Standard closure vs object initialized closure

I understand the typical retain cycle with a closure when referencing self within the closure, but is there a reason the label does not produce a retain cycle? 当我在闭包中引用self时,我了解带闭包的典型保留周期,但是是否有原因标签不产生保留周期? I've tested commenting the testClosure out vs commenting the label out and only the testClosure produced a retain cycle 我已经测试过注释掉testClosure与注释掉标签,只有testClosure产生了保留周期

class TargetView: UIView {

    let newText = "hi"
    var label = UILabel()

    private var counter = 0
    private var testClosure : (() -> ()) = { }

    init() {
        super.init(frame: .zero)
        // This causes a retain cycle
        testClosure = {
            self.counter += 1
            print(self.counter)
        }

        // This does NOT cause a retain cycle
        label = UILabel() {
            $0.text = self.newText
            self.counter += 1
        } 
    }

    required init?(coder aDecoder: NSCoder) { fatalError() }

    deinit {
        print("view deinit!")
    }
}

extension UILabel {
    convenience init(label: (UILabel) -> Void) {
        self.init()
        label(self)
    }
}

As already described in the comments: your custom initializer for UILabel just runs the label block but does not store (read: does not retain ) it, so no retain cycle can occur. 如注释中所述:您为UILabel定制的初始化UILabel只运行label块,但不存储(读取: 不保留 )它,因此不会发生保留周期。

Please not that from the outside you cannot determine whether a block parameter is retained, so unless this behaviour is documented or you wrote the code yourself, it's often better to use a weak reference just to be sure. 请不要从外部确定您是否保留了块参数,因此,除非对此行为进行了说明或您自己编写了代码,否则通常最好使用弱引用以确保确定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM