为什么将闭包 属性 更改为函数不会导致相同的保留周期?
Why doesn't changing a closure property to a function cause the same retain cycle?
A strong reference cycle can also occur if you assign a closure to a
property of a class instance, and the body of that closure captures
the instance.
如果作为属性的闭包会导致强保留循环,并且根据 Swift programming guide 函数是一种闭包类型:
Global and nested functions, as introduced in Functions, are actually
special cases of closures
为什么将闭包 属性 更改为实例方法不会导致相同的保留周期?
Instance methods are functions that belong to instances of a
particular class, structure, or enumeration.
例如,下面的代码不会释放 HTMLElement 的实例,但是,如果我将 asHTML
更改为函数而不是闭包表达式的名称,HTMLElement
被释放。
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
return "<\(self.name)>\(self.text ?? "")</\(self.name)>"
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {print("\(name) is being deinitialized")}
}
var headerTitle: HTMLElement? = HTMLElement(name: "h1", text: "Welcome")
print(headerTitle!.asHTML())
headerTitle = nil
调试器:
<h1>Welcome</h1>
更改为函数时:
func asHTML() -> String {
return "<\(self.name)>\(self.text ?? "")</\(self.name)>"
}
调试器:
<h1>Welcome</h1>
h1 is being deinitialized
当你将闭包保存到一个实例变量时,闭包会导致一个保留循环,所以你对闭包有一个强引用,然后闭包对持有它的对象有一个强引用。
在您的第一个示例中,您的 var asHTML 是一个保存到 HTMLElement
class 中的实例变量的闭包。这意味着 HTMLElement
实例保持对闭包的强引用。
然后在闭包中引用 self
。这意味着闭包持有对定义它的对象的强引用(同样,HTMLElement
实例。)您已经创建了一个保留周期。
现在,如果您调用了一个函数 asHTML()
,则您不会将该函数作为对象保存在某处。它是对象的实例方法。它引用了 self,因为它是 self 的 PART。因此没有保留周期。
A strong reference cycle can also occur if you assign a closure to a property of a class instance, and the body of that closure captures the instance.
如果作为属性的闭包会导致强保留循环,并且根据 Swift programming guide 函数是一种闭包类型:
Global and nested functions, as introduced in Functions, are actually special cases of closures
为什么将闭包 属性 更改为实例方法不会导致相同的保留周期?
Instance methods are functions that belong to instances of a particular class, structure, or enumeration.
例如,下面的代码不会释放 HTMLElement 的实例,但是,如果我将 asHTML
更改为函数而不是闭包表达式的名称,HTMLElement
被释放。
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
return "<\(self.name)>\(self.text ?? "")</\(self.name)>"
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {print("\(name) is being deinitialized")}
}
var headerTitle: HTMLElement? = HTMLElement(name: "h1", text: "Welcome")
print(headerTitle!.asHTML())
headerTitle = nil
调试器:
<h1>Welcome</h1>
更改为函数时:
func asHTML() -> String {
return "<\(self.name)>\(self.text ?? "")</\(self.name)>"
}
调试器:
<h1>Welcome</h1>
h1 is being deinitialized
当你将闭包保存到一个实例变量时,闭包会导致一个保留循环,所以你对闭包有一个强引用,然后闭包对持有它的对象有一个强引用。
在您的第一个示例中,您的 var asHTML 是一个保存到 HTMLElement
class 中的实例变量的闭包。这意味着 HTMLElement
实例保持对闭包的强引用。
然后在闭包中引用 self
。这意味着闭包持有对定义它的对象的强引用(同样,HTMLElement
实例。)您已经创建了一个保留周期。
现在,如果您调用了一个函数 asHTML()
,则您不会将该函数作为对象保存在某处。它是对象的实例方法。它引用了 self,因为它是 self 的 PART。因此没有保留周期。