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

时间:2018-01-25 02:19:44

标签: swift function memory-management closures automatic-ref-counting

  

如果为a分配闭包,也会出现强引用循环   类实例的属性,该闭包的主体捕获   实例。

如果作为属性的闭包可以导致强保留周期,并且函数是根据Swift programming guide的一种闭包:

  

实际上,函数中引入的全局函数和嵌套函数   特殊情况的封闭

为什么不将闭包属性更改为实例方法会导致相同的保留周期?

  

实例方法是属于a实例的函数   特定的类,结构或枚举。

例如,按原样,下面的代码不会解除分配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

1 个答案:

答案 0 :(得分:1)

当你将一个闭包保存到一个实例变量时,闭包会导致一个保留周期,所以你有一个对闭包的强引用,然后闭包有一个对它的对象的强引用。

在第一个示例中,var asHTML是保存到HTMLElement类中的实例变量的闭包。这意味着HTMLElement实例保留了对闭包的强引用。

然后在你的闭包中你引用self。这意味着闭包具有对定义它的对象的强烈引用(同样,HTMLElement实例。)您已经创建了一个保留周期。

现在,如果你有一个你调用的函数asHTML(),你就不会将该函数保存为某个对象。它是对象的实例方法。它提到了自我,因为它是自我的 PART 。因此没有保留周期。