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.我认为我必须使用它,否则我会得到泄漏的记忆.
这里 :
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被声明为unowned在capture lists,因为它是安全的假设,这将不成为nil的任何一点.如果您确定该变量永远不会是nil,请使用,unowned但如果您认为它可能会变成某个点nil,请weak改用.