學(xué)習(xí)和研究的主要是“實(shí)例對象和實(shí)例對象直接的相會強(qiáng)引用所產(chǎn)生的內(nèi)從泄漏”和“使用閉包產(chǎn)生的強(qiáng)引用造成的內(nèi)存泄漏”
注意:只有以引用類型存儲或者傳遞的才會存在自動引用計(jì)數(shù),比如類,閉包,而枚舉、結(jié)構(gòu)體等這都是值存儲,值傳遞不存在引用計(jì)數(shù)問題(其實(shí)也就是Object-c中我們熟悉的ARC,和他的原理是一樣的)
實(shí)例對象和實(shí)例對象之間的相互引用造成的內(nèi)存泄漏
1>產(chǎn)生原因
兩個(gè)類中都有對方類的實(shí)例變量作為自己的屬性,舉個(gè)例子:創(chuàng)建一個(gè)Person類和一個(gè)Clazz類
Class Person {
var clazz:Clazz?
}
Class Clazz {
var person:Person?
}
// 創(chuàng)建兩個(gè)對象,并且賦值給對方就會造成循環(huán)引用
let jason = Person()
let class1_1 = Clazz()
jason.clazz = class1_1
class1_1.person = jason
上面的例子,就是一個(gè)循環(huán)引用的例子,jason->Person<->class1_1->Clazz .
2> 那么該怎么解決這個(gè)問題呢
在Objective-C中我們知道解決這種類與類之間的強(qiáng)引用,就是聲明屬性的時(shí)候一個(gè)用強(qiáng)引用一個(gè)用弱引用,那么在swift中是如何解決這種問題的呢?
swift 提供了兩種方式:弱引用(weak修飾)和無主引用(unowned修飾)
使用法則:弱引用在生命周期內(nèi)有可能變成nil使用,一旦申明就不會變成nil用無主引用 。
事實(shí)上規(guī)則還是和objective-C的規(guī)則一樣,遇到這種情況也是一個(gè)用強(qiáng)引用一個(gè)用弱引用或者無主引用。
注意:存在一種特殊的情況,那就是這兩個(gè)類各自持有的對方實(shí)例對象都必須有值,那么這種情況就需要一個(gè)用無主引用,一個(gè)用隱式展開可選屬性
閉包循環(huán)引用造成的內(nèi)存泄漏
1>造成原因:這是一種閉包和類之間的引用造成的。具體原因就是:一個(gè)類將閉包作為自己的屬性,然后在類中給閉包賦值,在閉包中又引用了自身,造成循環(huán)引用,內(nèi)存泄漏
2>解決問題的辦法
在objective-C中我們解決的辦法就是重新聲明類實(shí)例為__weak/__block,兩個(gè)修飾詞的區(qū)別是__weak只能修飾對象,而__block可以修飾對象和普通變量(需要在block里修改的變量)
而在swift中出現(xiàn)了一個(gè)新的概念:占有列表,在swift就是通過定義占有列表來解決閉包的循環(huán)引用的
占有列表:占有列表中的每個(gè)元素都是由weak或者unowned關(guān)鍵字和實(shí)例的引用組成的。
那么什么時(shí)候用weak:當(dāng)占有的引用有時(shí)可能為nil的時(shí)候
unwoned:當(dāng)占有的引用和閉包總是會同時(shí)銷毀時(shí)