现在当一个闭包在其体内引用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;
答案 0 :(得分:1)
通过关闭避免强引用周期的正确方法是将self
标记为unowned
或weak
,例如
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)>"
}