困惑关闭强大的参考周期?

时间:2015-11-19 06:03:22

标签: swift reference closures automatic-ref-counting strong-references

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是什么意思?

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

1 个答案:

答案 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

  

在闭包的特定情况下,您只需要意识到在其中引用的任何变量都由闭包“拥有”。只要封闭物周围,这些物体就可以保证在周围。阻止这种所有权的唯一方法是做[无主自我]或[弱自我]。

本质上是一个强大的参考周期:

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

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

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

第3

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

4

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

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

someFunction() // 10
someFunction(5) // 5