【iOS出租屋進(jìn)階】之內(nèi)存管理

基礎(chǔ)知識

iOS提供了兩種管理內(nèi)存的方式,分別為MRC(手動)和ARC(自動)。

MRC(人工引用計數(shù)),手動管理內(nèi)存。

MRC模式下,所有的對象都需要手動的添加retain、release代碼來管理內(nèi)存。使用MRC,需要遵守誰創(chuàng)建,誰回收的原則。也就是誰alloc,誰release;誰retain,誰release。
當(dāng)引用計數(shù)為0的時候,必須回收,引用計數(shù)不為0,不能回收,如果引用計數(shù)為0,但是沒有回收,會造成內(nèi)存泄露。如果引用計數(shù)為0,繼續(xù)釋放,會造成野指針。為了避免出現(xiàn)野指針,我們在釋放的時候,會先讓指針=nil。

ARC(自動引用計數(shù)),自動管理內(nèi)存。

在ARC模式下,只要沒有強(qiáng)指針(強(qiáng)引用)指向?qū)ο?,對象就會被釋放。在ARC模式下,不允許使用retain、release、retainCount等方法。并且,如果使用dealloc方法時,不允許調(diào)用[super dealloc]方法。
ARC模式下的property變量修飾詞為strong、weak,相當(dāng)于MRC模式下的retain、assign。strong :代替retain,缺省關(guān)鍵詞,代表強(qiáng)引用。weak:代替assign,聲明了一個可以自動設(shè)置nil的弱引用,但是比assign多一個功能,指針指向的地址被釋放之后,指針本身也會自動被釋放。

@property修飾的內(nèi)存管理

MRC : retain、assign、copy
ARC : strong、weak、copy

關(guān)于棧和堆

棧(stack): 由編譯器自動分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等
堆(heap): 一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時可能由系統(tǒng)回收

OC對象存放于堆里面(堆內(nèi)存要程序員手動回收)
非OC對象一般放在棧里面(棧內(nèi)存會被系統(tǒng)自動回收)
我們創(chuàng)建一個oc對象,定義一個變量,調(diào)用一個函數(shù)或者方法都會提高App的內(nèi)存占用。

內(nèi)存泄露和過度釋放

iOS開發(fā)過程中,使用Objective-C分配的堆內(nèi)存都是通過引用計數(shù)來做保留和釋放的。一塊內(nèi)存初始分配,引用計數(shù)為1,此后每新增一個強(qiáng)引用,引用計數(shù)增加1;釋放正好相反,每一次release,引用計數(shù)減1,直到為0,對象所用內(nèi)存被真正free掉,以被再次復(fù)用。然而,實際開發(fā)當(dāng)中,總有一些原因?qū)е乱糜嫈?shù)無法按正常邏輯減少到0,或者減少到0之后仍然被調(diào)用release,前者是內(nèi)存泄露,后者則是過度釋放。

當(dāng)內(nèi)存泄露發(fā)生時,運(yùn)行的App不會直接第發(fā)生明顯問題,但廢棄內(nèi)存得不到回收,在長時間持續(xù)運(yùn)行后,App進(jìn)程會由于可用內(nèi)存不斷變低而被kill或帶來其它隱患。(內(nèi)存泄露的隱患)
過度釋放,是對同一個對象釋放了過多的次數(shù),其實當(dāng)引用計數(shù)降到0時,對象占用的內(nèi)存已經(jīng)被釋放掉,此時指向原對象的指針就成了“懸垂指針”,如若再對其進(jìn)行任何方法的調(diào)用,(原則上)都會直接crash(然而由于某些特殊的情況,不會馬上crash)。(過度釋放的隱患)

內(nèi)存工具(Instruments)

內(nèi)存泄漏

為了更好地處理內(nèi)存泄露的問題,平時在寫代碼的時候要注意循環(huán)引用,學(xué)會善用weak,良好的編程習(xí)慣,檢查一些顯而易見的語法問題。
對于運(yùn)行時出現(xiàn)的問題,我們可用 Instruments 中的 AllocationLeaks 來不斷重復(fù)操作App,發(fā)現(xiàn)和定位內(nèi)存泄露點。當(dāng)運(yùn)行時發(fā)生顯示內(nèi)存泄露時, Leaks 會在時間軸上標(biāo)出紅色指示線,同時在 Instruments 的下方會列出調(diào)用細(xì)節(jié),結(jié)合系統(tǒng)提供的 malloc 歷史,其中包含引用計數(shù)變化情況,以及調(diào)用??梢院苤苯拥卣业叫孤对颉?br> 同時對于一些“隱式”的情況,需要反復(fù)操作,同時觀察 Allocation 中只增不減,一直創(chuàng)建新對象而不釋放老對象的情況。

野指針與僵尸對象

野指針:指針指向的對象已經(jīng)被回收掉了,這個指針就叫做野指針
僵尸對象:一個已經(jīng)被釋放的對象,就叫做僵尸對象
詳情點這里
我們有兩種方式找到產(chǎn)生的原因:
1.使用 InstrumentsZombies 工具 詳情點這里
2.手動開啟 Product->Scheme->Edit Scheme->Run xxx.app,在右邊框中選中 Enable Zombie Objects(手動開啟僵尸對象,會導(dǎo)致內(nèi)存增長,也會影響 Leaks 工具的調(diào)試)

iOS應(yīng)用性能調(diào)優(yōu)的25個建議和技巧

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容