2
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在闭包中不为人所知有关,但对于尚未创建的init方法来说,情况不一样吗?self

其次,这个代码示例中的强引用循环到底在哪里,是否self是强引用asHTML,如果是,导致循环的强引用的第二部分在哪里?

text第三,当常量不能改变值时,为什么常量属性是可选的(从nil到一个值并返回到nil)?

最后,当方法用于接受用户发送的参数时,方法中有参数text: String? = nil是什么意思?initinit

抱歉这个长问题,我只是对闭包强引用循环感到困惑......虽然我确实理解类属性和类实例之间的强引用循环。

4

1 回答 1

1

1

lazy用于仅在调用时创建的属性。所以在你打电话之前myClass.myLazyAttribute它不会占用任何空间。这也意味着它将在类初始化后初始化,这非常有用。

在这种情况下lazy,用于访问self,就像您所说的那样,因为self在实例初始化之前不可用。

2

代码所在的苹果文档。

闭包捕获其中使用的值。在这种情况下,它捕获self. 它不会在 A 类和 B 类之间创建强引用循环,而是在其自身和闭包之间创建强引用循环。如果您想象闭包内的操作需要很长时间,那就更有意义了。在执行期间发生了其他事情,您想要取消初始化实例。但是闭包已被捕获self,它将使实例保持活动状态,直到完成为止。

通过使用[unowned self] in,您可以在闭包运行时再次取消实例。尽管这会使您的应用程序崩溃。

关于这个特定用途的好信息:链接

在闭包的特定情况下,您只需要意识到在其中引用的任何变量都会被闭包“拥有”。只要闭包在附近,这些对象就保证在附近。阻止这种所有权的唯一方法是做[无主的自我]或[弱自我]。

什么是强参考循环本质上是:

  • 你有一个类的实例
  • 实例的引用计数高于 0
  • 不再有对您的程序可用的实例的引用。

甚至更短:实例的引用计数高于可访问引用的数量。

在这种情况下,引用计数self增加 1,因为它被闭包捕获。我们无法访问该引用,因为我们无法说出类似的内容:closure.selfAttribute,因此我们无法将其设置为nil。只有当闭包完成时,引用计数才会再次减 1。

3

它是一个可选常量,但它的初始值是在类的 init 方法中设置的。所以它可以在 init 方法中接收一个值,但它是不可变的。这称为后期初始化

4

这是一个具有默认值的函数参数。

func someFunction(myParamWithDefaultValue : Int = 10) {
    print(myParamWithDefaultValue)
}

someFunction() // 10
someFunction(5) // 5
于 2015-11-19T06:28:18.887 回答