我正在阅读Apple的《 Swift编程语言指南》.在有关闭合的强引用循环的部分中,我尝试了另一种类型的闭合,但未给出预期的输出.
I am reading Apple's Swift Programming Language Guide. In the part about Strong Reference Cycle for closures, I tried a different type of closure but it did not give the expected output.
class HTMLElement { let name: String let text: String? lazy var asHTML : String = { //[unowned self] in if let text = self.text { return "<\(self.name)>\(text)</\(self.name)>" } else { return "<\(self.name) />" } }() init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { println("\(name) is being deinitialized") } } var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") println(paragraph!.asHTML) paragraph = nil此代码的输出是:
<p>hello, world</p> p is being deinitialized即使没有[unown self],也会打印"p正在被初始化"
"p is being deinitialised" is printed even without [unowned self]
指南中的代码为:
class HTMLElement { let name: String let text: String? lazy var asHTML: () -> String = { [unowned self] in if let text = self.text { return "<\(self.name)>\(text)</\(self.name)>" } else { return "<\(self.name) />" } } init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { println("\(name) is being deinitialized") } } var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") println(paragraph!.asHTML) paragraph = nil仅当添加[unown self]语句时,此命令才会显示取消初始化消息.
This prints the deinitialiser message only when the [unowned self] statement is added.
两个闭包之间有什么区别?
What is the difference between both the closures?
推荐答案好问题!为了对其进行探索,我们应该将测试用例简化为证明它所需的最小数量:
Great question! To explore it, we should simplify the test case to the minimum required to demonstrate it:
// First case, a lazy string class LazyVar { let name = "LazyVar" lazy var lazyName : String = { return self.name }() deinit { println("\(name) is being deinitialized") } } var lazyVar: LazyVar? = LazyVar() println(lazyVar?.lazyName) lazyVar = nil // Calls deinit // Second case, a lazy ()->String class LazyFunc { let name = "LazyFunc" lazy var lazyFunc: () -> String = { // [unowned self] in // <-- This would break the loop return self.name } deinit { println("\(name) is being deinitialized") } } var lazyFunc: LazyFunc? = LazyFunc() println(lazyFunc?.lazyFunc()) lazyFunc = nil // Doesn't call deinit在第一种情况下,没有永久的保留循环.当您访问lazyName时,闭包将被评估为{ return self.name }.该闭包捕获self,计算一个字符串,然后返回该字符串.该字符串已分配给属性.现在,我们已经完成了关闭,因此已将其释放,并释放了self.请注意,这里有一个简短的保留循环,但是没关系.最终它被打破了,这就是一切.
In the first case, there is no permanent retain loop. When you access lazyName, a closure is evaluated { return self.name }. That closure captures self, computes a string, and returns the string. The string is assigned to the property. We're now done with the closure, so it's released, and it releases self. Note that there is a brief retain loop here, but that's ok. It is eventually broken, and that's all that matters.
在第二种情况下,存在一个永久的保留循环.当您访问lazyFunc()时,它将调用一个闭包,该闭包将创建一个新闭包.该新的闭包是{return self.name},并且已分配给该属性.而且该闭包保留self,因此永不中断的保留循环也是如此.将[unowned self] in添加到lazyFunc中,将为您打破循环.
In the second case, there is a permanent retain loop. When you access lazyFunc(), it calls a closure that creates a new closure. That new closure is {return self.name}, and that is assigned to the property. And that closure retains self, so is a retain loop that is never broken. Adding [unowned self] in to lazyFunc as marked would break the loop for you.
更多推荐
不同的闭合为保留周期提供了不同的结果
发布评论