在进行惰性变量,内存管理时,我们是否需要弱或无主参考?

ton*_*ran 2 memory-leaks memory-management lazy-evaluation swift

我正在通过以下方式在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
Run Code Online (Sandbox Code Playgroud)

如你所见,我self在声明一个懒惰的var时使用内部,我认为它仍然可以,因为当p2变为nil时,我可以看到该deinit方法被调用.

但是,如果我做了如下更改

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

现在,我得到了一个泄漏的记忆.

我的问题是使用延迟实例化的变量,为什么我没有得到泄漏的内存,即使我正在使用self.我认为我必须使用它,否则我会得到泄漏的记忆.

Der*_*123 7

这里 :

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

您将闭包本身分配给变量,而不是分配String它应该返回的变量.而且由于你正在使用self闭合器保留的东西,这两个将永远不会释放,这可能导致一个memory leak.甲reference cycle作为封闭件被保持为一个属性被创建和封闭保留自我.这是capture lists进入图片的地方.您可以像这样修复泄漏:

private lazy var clone: () -> String  = { [unowned self] in

        return self.name    // leaking memory is fixed
    }
Run Code Online (Sandbox Code Playgroud)

Self被声明为unownedcapture lists,因为它是安全的假设,这将成为nil的任何一点.如果您确定该变量永远不会nil,请使用,unowned但如果您认为它可能会变成某个点nil,请weak改用.