快速保留周期缺失澄清

时间:2019-05-04 00:03:51

标签: ios swift iphone automatic-ref-counting

苹果有documentation that describes how retain cycles work in closures。这是他们不会造成保留周期的关闭示例。

class HTMLElement {

    let name: String
    let text: String?

    lazy var asHTML: () -> String = {
        [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) is being deinitialized")
    }

}

我偶尔喜欢将函数定义传递给回调,以尝试摆脱回调地狱的代码。

这个例子有些人为,但这会导致保留周期吗?将这样的函数分配给闭包是否会导致保留周期?

class HTMLElement {

    let name: String
    let text: String?

    lazy var asHTML: () -> String = self.returnHTML

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    func returnHTML() -> String {
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }

    deinit {
        print("\(name) is being deinitialized")
    }

}

1 个答案:

答案 0 :(得分:2)

实际上,您的示例不够人为。让我们变得更简单:

class C {
    lazy var f: () -> () = {
        [unowned self] in
        print(self)
    }
    init() {}
    func doF() {
        self.f()
    }
    deinit {
        print("C is being deinitialized")
    }
}

现在让我们对其进行测试:

    let c = C()
    c.doF()

结果:当c超出范围时,我们看到“ C正在被初始化”。

好的,但是现在删除[unowned self] in。现在,当我们对其进行测试时,我们不要看到“ C正在被初始化”。我们有一个保留周期。

是的,您有self个保留引用self的函数,这是一个保留周期。您可以通过unowned self来打破循环。

(当然,在我的示例中,我考虑的是您的lazy使图片复杂化的方式。如果我们不说self.f(),也就是说,我们从不问{ {1}}进行自身初始化–当然,lazy var的初始化器是什么没关系:它永远不会被初始化,所以不会有保留周期。极不可能的情况;如果您永远不会初始化f,那么您就不会以lazy var开始。)