【问题标题】:Confused on closure strong reference cycle?对关闭强引用循环感到困惑?
【发布时间】:2016-02-21 03:39:21
【问题描述】:
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,如果是,那么导致循环的强引用的第二部分在哪里?

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

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

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

【问题讨论】:

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


    【解决方案1】:

    1

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

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

    2

    The apple doc from where code is.

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

    通过使用[unowned self] in,您可以在闭包运行时再次取消初始化实例。虽然这会使您的应用崩溃。

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

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

    什么是强引用循环:

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

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

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

    3

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

    4

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

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

    【讨论】:

    • 请注意,weakunowned 都不是强引用
    • 好的,现在我有一个问题,如果我创建HTMLElement 类的实例,文档说会有一个强大的引用循环,我理解他们的意思的一半...... ...闭包使用 self.name 和 self.text “捕获” self 并对 HTMLElement 类的实例进行强引用.....现在如何从实例返回闭包的强引用??
    • @Ali 那么我需要知道对方的样子。还有这个代码是从哪里来的。您提到了文档,那么这是教程还是框架?
    • @Fawkes 抱歉回复晚了。如果您在闭包中捕获self,并且此闭包是一个长操作(网络请求),并且在操作完成时不再有任何其他对self 的引用,self 将被释放。
    猜你喜欢
    • 2018-10-03
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    • 2016-07-13
    • 2017-05-03
    • 1970-01-01
    相关资源
    最近更新 更多