去初始化,自我和封闭。

时间:2017-09-06 16:29:35

标签: swift

现在当一个闭包在其体内引用self时,闭包捕获self,这意味着它拥有一个强引用回HTMLElement实例(见下文)。在两者之间创建了强大的参考周期。这意味着实例不会取消初始化(如下所示);然而,当我试图将自我替换为标题(实例)时,去除了确实有效,这意味着没有强大的参考周期。我的理解是,在这种情况下,标题与自我相同,因为自我就是实例本身。那么为什么当我用实例替换它时,实例会取消初始化'标题'?

class HTMLElement {

let name: String
let text: String?

lazy var asHTML: () -> String = {
    let defaultText = "some default text"
    return "<\(heading.name)>\(heading.text ?? defaultText)</\(heading.name)>"
}
init(name: String, text: String? = nil) {
    self.name = name
    self.text = text
}

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

}
var heading = HTMLElement(name: "h1")
let defaultText = "some default text"

print(heading.asHTML())
// Prints "<h1>some default text</h1>”
heading = HTMLElement(name: "h4")

输出:

< h1 > some default text < /h1 >
h1 is being deinitialized

现在如果关闭被替换如下:

lazy var asHTML: () -> String = {
let defaultText = "some default text"
return "<\(self.name)>\(self.text ?? defaultText)</\(self.name)>"
}
输出将是:

&LT; h1&gt;一些默认文字&lt; / h1&gt;

1 个答案:

答案 0 :(得分:1)

通过关闭避免强引用周期的正确方法是将self标记为unownedweak,例如

class HTMLElement {

    let name: String
    let text: String?

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

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

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

}

这就引出了为什么你不使用函数

的问题
func asHTML() -> String {
    let defaultText = "some default text"
    return "<\(name)>\(text ?? defaultText)</\(name)>"
}

或计算属性:

var asHTML: String {
    let defaultText = "some default text"
    return "<\(name)>\(text ?? defaultText)</\(name)>"
}