2016-08-02 23 views
1

我正在用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。我以爲我必須使用它,否則我會得到一個泄漏的內存。

回答

1

你泄漏內存的原因是因爲在默認情況下,閉包會強烈地捕獲自己,並且同時自己將閉包強烈地視爲屬性。它與懶惰變量無關。

+0

這是我在發佈之前所想的。我想確保我的想法是正確的。謝謝 – tonytran

6

這裏:

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

你分配的,而不是分配,它應該返回String蓋子本身的變量。並且由於您使用的是self,其中封閉保留,因此兩者將永遠不會被釋放,這可能會導致memory leak。 A reference cycle是在封閉作爲屬性保留並且封閉保留自己時創建的。這裏是capture lists的照片。您可以修復泄漏,像這樣:

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

     return self.name // leaking memory is fixed 
    } 

Self被聲明爲unownedcapture lists,因爲它是安全的假設,它會nil在任何點。如果您確定變量將NEVERnil,使用unowned但如果你認爲在某個時候可能成爲nil,使用weak代替。