为什么将闭包 属性 更改为函数不会导致相同的保留周期?

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。因此没有保留周期。