【问题标题】:do we need weak or unowned reference when doing a lazy variable, memory management在执行惰性变量、内存管理时,我们是否需要弱引用或无主引用
【发布时间】:2016-12-08 02:27:50
【问题描述】:

我正在通过以下方式在 Swift 中尝试内存管理。

class Person {
    let name: String
    //var block: (() -> Void)?

    init(name: String) {
        self.name = name
    }

    //  Declare variable clone, using self inside.
    private lazy var clone: String  = {
        return self.name   
    }()

    deinit {
        print("Destroying \(name)")
    }
    func doSomething() {
        print("Doing something for \(name)")
    }
}

var p2: Person? = Person(name: "p2")
print(p2!.clone)
p2 = nil

如您所见,我在声明惰性 var 时使用了 self 内部,我认为它仍然可以,因为当 p2 变为零时,我可以看到 deinit 方法被调用。

但是,如果我进行如下更改

    // This is a closure
    private lazy var clone: () -> String  = {
        return self.name    // leaking memory is here
    }

现在,我的内存泄漏了。

我的问题是关于使用延迟实例化的变量,为什么即使我使用self 也不会出现内存泄漏。我想我必须使用它,否则我会得到内存泄漏。

【问题讨论】:

    标签: swift memory-management memory-leaks lazy-evaluation


    【解决方案1】:

    你泄漏内存的原因是因为闭包会在默认情况下强烈地捕获 self ,同时 self 会强烈地将闭包作为一个属性。它与惰性变量无关。

    【讨论】:

    • 这是我发帖前的想法。我想确保我的想法是正确的。谢谢
    【解决方案2】:

    这里:

     private lazy var clone: () -> String  = {
            return self.name    // leaking memory is here
        }
    

    您将闭包本身分配给变量,而不是分配它应该返回的String。而且由于您使用的是闭包保留self,因此这两个将永远不会被释放,这可能会导致memory leakreference cycle 被创建为闭包被保留为属性并且闭包保留自我。这是capture lists 出现的地方。您可以像这样修复泄漏:

    private lazy var clone: () -> String  = { [unowned self] in
    
            return self.name    // leaking memory is fixed
        }
    

    Selfcapture lists 中被声明为unowned,因为可以安全地假设它在任何时候不会nil。如果您确定变量永远不会nil,请使用unowned,但如果您认为在某个时候它可能变为nil,请改用weak .

    【讨论】:

      猜你喜欢
      • 2015-12-28
      • 1970-01-01
      • 2021-08-29
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 2019-08-07
      • 2012-06-17
      • 2023-03-11
      相关资源
      最近更新 更多