深入講解Swift的內(nèi)存管理
前言
LLVM編譯器的好:Swift的內(nèi)存管理除了要注意引用循環(huán)之外,幾乎全部被LLVM編譯器包攬,不需要開發(fā)人員操心。
Swift 是自動(dòng)管理內(nèi)存的,這也就是說,我們不再需要操心內(nèi)存的申請和分配。當(dāng)我們通過初始化創(chuàng)建一個(gè)對象時(shí),Swift 會(huì)替我們管理和分配內(nèi)存。而釋放的原則遵循了自動(dòng)引用計(jì)數(shù) (ARC) 的規(guī)則:當(dāng)一個(gè)對象沒有引用的時(shí)候,其內(nèi)存將會(huì)被自動(dòng)回收。這套機(jī)制從很大程度上簡化了我們的編碼,我們只需要保證在合適的時(shí)候?qū)⒁弥每?(比如超過作用域,或者手動(dòng)設(shè)為 nil 等),就可以確保內(nèi)存使用不出現(xiàn)問題。
但是,所有的自動(dòng)引用計(jì)數(shù)機(jī)制都有一個(gè)從理論上無法繞過的限制,那就是循環(huán)引用 (retain cycle) 的情況。
引用循環(huán)問題是什么
Swift 使用 ARC(自動(dòng)引用計(jì)數(shù))的方法為引用類型管理內(nèi)存。
在 Swift 中,當(dāng)聲明引用類型的變量并將對象負(fù)值給他時(shí),相當(dāng)于創(chuàng)建了對該對象的強(qiáng)引用,該對象的引用計(jì)數(shù)將加1。如果兩個(gè)對象相互強(qiáng)引用,將導(dǎo)致引用循環(huán)。引用循環(huán)一旦出現(xiàn),相關(guān)的對象將無法釋放,從而產(chǎn)生內(nèi)存泄漏。
引用循環(huán)問題出現(xiàn)的場景與解決辦法
Swift中類對象和閉包都是通過引用進(jìn)行傳值,所以以下場景會(huì)出現(xiàn)引用循環(huán):
類對象相互強(qiáng)引用
兩個(gè)對象彼此引用對方時(shí),形成引用循環(huán)。
class Letter {
let addressedTo: String
var mailbox : MailBox?
init( addressedTo: String) {
self. addressedTo = addressedTo
}
deinit {
printl(" The letter addressed to \(addressedTo) is being discarded")
}
}
class MailBox {
let poNumber: Int
var letter : Letter?
init( poNumber: Int) {
self. poNumber = poNumber
}
deinit {
print(" P.O Box \(poNumber is going away)")
}
}
Letter 類中強(qiáng)引用了 MailBox 類對象,MailBox 類中又強(qiáng)引用了 Letter 類對象形成引用循環(huán)。
解決辦法:聲明對象時(shí)加入 weak 關(guān)鍵字(弱引用)可以解除強(qiáng)引用。比如將 letter 對象聲明為 weak 時(shí),mailbox 對象的引用計(jì)數(shù)不會(huì)加1,從而解除引用循環(huán)。一般將邏輯上屬于另一對象的對象聲明為弱對象。如:
weak var letter : Letter?
閉包中引用包含自身的對象
閉包中引用包含自身的對象也會(huì)造成引用循環(huán)。
class MailChecker {
let mailbox: MailBox
let letter: Letter
lazy var whoseMail: () -> String = {
return "Letter is addressed to \(self. letter.addressedTo)"
}
init(name: String) {
self. mailbox = MailBox( poNumber: 311)
self. letter = Letter( addressedTo: name)
}
deinit {
println(" class is being deintialized")
}
}
示例代碼中 whoseMail 的閉包中使用 self 引用了包含自身的 MailChecker 對象,此時(shí)該閉包擁有 MailChecker 對象,而 MailChecker 對象又擁有該閉包,導(dǎo)致引用循環(huán)。
解決辦法:此時(shí)可以添加[unowned self]讓 Swift 知道不應(yīng)保留 self 對象,從而解除引用循環(huán)。將閉包改為:
lazy var whoseMail: () -> String = { [unowned self] in
return "Letter is addressed to \(self. letter.addressedTo)"
}
注:代碼均取自 Boisy G. Pitre《Swift基礎(chǔ)教程》
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對各位iOS開發(fā)者們能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
Swift利用指紋識別或面部識別為應(yīng)用添加私密保護(hù)功能
這篇文章主要給大家介紹了關(guān)于Swift利用指紋識別或面部識別為應(yīng)用添加私密保護(hù)功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用swift具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友下面隨著小編來一起看看吧2018-05-05
詳解在swift中實(shí)現(xiàn)NSCoding的自動(dòng)歸檔和解檔
本篇文章主要介紹了在swift中實(shí)現(xiàn)NSCoding的自動(dòng)歸檔和解檔,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03
Swift編程中用以管理內(nèi)存的自動(dòng)引用計(jì)數(shù)詳解
這篇文章主要介紹了Swift編程中用以管理內(nèi)存的自動(dòng)引用計(jì)數(shù)詳解,是Swift入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-11-11
利用Swift實(shí)現(xiàn)各類的CATransition動(dòng)畫詳解
CATransition動(dòng)畫主要在過渡時(shí)使用,比如兩個(gè)頁面層級改變的時(shí)候添加一個(gè)轉(zhuǎn)場效果。CATransition分為兩類,一類是公開的動(dòng)畫效果,一類是非公開的動(dòng)畫效果。這篇文章主要給大家介紹了關(guān)于如何利用Swift實(shí)現(xiàn)各類CATransition動(dòng)畫的相關(guān)資料,需要的朋友可以參考下。2017-09-09
Swift內(nèi)置的數(shù)字類型及基本的轉(zhuǎn)換方法
這篇文章主要介紹了Swift內(nèi)置的數(shù)字類型及基本的轉(zhuǎn)換方法,是Swift入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-11-11
Swift之UITabBarController 導(dǎo)航控制器的自定義
本文給大家介紹swift導(dǎo)航控制器之UITabBarController,本文通過代碼實(shí)例給大家講解swift導(dǎo)航控制器,導(dǎo)航控制器類繼承UITabBarController,代碼簡單易懂,需要的朋友可以參考下2015-10-10

