class HTMLElement {
let name : String
let text: String?
//Declaring a lazy variable that has a strong reference to this closure
lazy var asHTML: Void -> String = {
//Optional binding here
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 {
print("\(name) is being deinitialized")
}
}
我的问题是:为什么闭包声明为Lazy,我知道它与self
在闭包中不知道有关,但并不是{{1}的相同情况} {还没有创建init
的方法?
其次,这个代码示例中的强引用周期究竟在哪里,是self
强烈引用self
,如果是这样,强引用的第二部分导致循环?
第三,为什么当常量不能改变值(从asHTML
到值并返回到text
)时,常量nil
属性是可选的?
最后,当nil
方法用于接受用户发送的参数时,在text: String? = nil
方法中使用参数init
是什么意思?
很抱歉这个长期的问题,我只是对闭包强引用周期感到困惑....虽然我确实理解类属性和类实例之间的强引用循环。
答案 0 :(得分:1)
<强> 1 强>
lazy
用于仅在调用时创建的属性。因此,在致电myClass.myLazyAttribute
之前,它不会占用任何空间。这也意味着它会在类初始化之后初始化,这可能非常有用。
在这种情况下,lazy
用于访问self
,就像您所说的那样,因为self
在实例初始化之前不可用。
<强> 2 强>
The apple doc from where code is.
Closures捕获其中使用的值。在这种情况下,它会捕获self
。
它不会在A类和B类之间创建强引用循环,但在它自身和闭包之间。如果你想象闭包内部的操作需要很长时间,那就更有意义了。在执行期间发生了其他事情并且您想要取消实例。但是闭包已经捕获了self
,它将使实例保持活着状态直到完成。
通过使用[unowned self] in
,您可以在闭包运行时再次取消实例。虽然这会让你的应用程序崩溃。
有关此特定用途的详细信息:link
在闭包的特定情况下,您只需要意识到在其中引用的任何变量都由闭包“拥有”。只要封闭物周围,这些物体就可以保证在周围。阻止这种所有权的唯一方法是做[无主自我]或[弱自我]。
本质上是一个强大的参考周期:
甚至更短:实例的引用计数高于可访问引用的数量。
在这种情况下,self
的引用计数增加1,因为它被闭包捕获。我们无法访问该引用,因为我们无法说出closure.selfAttribute
之类的内容,因此我们无法将其设置为nil
。只有当关闭完成后,引用计数才会再次下降。
第3 强>
它是可选常量,但它的初始值是在类的init方法中设置的。所以它可以在init方法中接收一个值,但它将是不可变的。这称为晚期初始。
4
这是一个带有默认值的函数参数。
func someFunction(myParamWithDefaultValue : Int = 10) {
print(myParamWithDefaultValue)
}
someFunction() // 10
someFunction(5) // 5