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