iOS開發基礎之內存管理

為什么要進行內存管理

  • Objective-C不像JAVA和C#等語言,內存管理依賴垃圾回收(GC)機制;它需要開發者自己管理內存,即便目前的ARC機制也只是編譯器幫助開發者完成一部分工作,實際開發中還是需要時刻關注程序的內存相關;
  • iOS程序員創建的對象大多分配在堆上,存儲空間有限,在iOS系統中如果app內存使用量過大,會收到內存預警的消息,不作處理的情況下系統可能會強制清理程序; 因此內存管理對移動端開發尤為重要;

如何進行內存管理

使用引用計數的方式對創建的對象進行內存的管理操作;有強引用指向(retain)那么引用計數+1,強引用被置為nil(release)那么引用計數-1;對象超過作用域該對象的引用計數如果為0,則系統會清理對象占用的內存空間,目前內存管理的方式分為MRC和ARC兩種.

  • MRC:需要開發者編碼追加retain/release等消息;
  • ARC:編譯器為開發者追加retain/release等消息;

引用計數是什么

  • 內存管理中對引用自動計數的技術;
  • 簡單的說是一個數值,可以通過對象的retainCount獲取 ;這個數值為0時代表給對象可以被系統回收;
  • 引用計數采用散列表的方式存儲,對象的內存地址作為key,value就是對象的retainCount;

內存管理的思考方式

  • 自己生成的對象自己持有(new、 alloc、 copy、 mutablecopy) ;
  • 非自己生成的對象自己也能持有 ;
  • 不需要自己持有的對象時釋放 ;
  • 非自己持有的對象無法釋放 ,使用autorelease機制生成的對象,一旦持有就不需要自己釋放,一旦釋放就會導致崩潰問題;

autorelease的作用

  • 生成的對象不自己持有,但能保證對象在超出作用域范圍存在并能正確地釋放
  • 將對象添加到autoreleasepool中;
  • 在對象超過autoreleasepool的作用域,向對象發送release消息;
  • 像NSMutableArray的類方法+array內部生成對象就使用了autorelease;

autorelease的實現 (GNUStep)

  • autorelease實例方法的本質就是調用NSAutoreleasePool的addObject:類方法 ;
  • 關于autorelease的頻繁調用,系統的解決機制是使用"IMP Caching",每一個類都有一個方法緩存列表,這樣就能提高在運行時頻繁調用某個方法的效率 ;

autorelease的實現 (Apple)

autorelease的實現

autoreleasepool

  • 使用autorealease標記的對象都會被注冊到自動釋放池中,當自動釋放池被drain時會向存儲的對象一一發送release消息
  • autorealeasepool類似一個堆棧,提供pop();push();removeAll();方法。一次runloop循環就會創建一個autorealeasepool,事件循環結束自動釋放池銷毀,對象realease;引用計數為0的銷毀,不為0的可能會出現內存泄露的問題

手動創建autoreleasepool的情況

當開發中遇到在某個作用域內部產生大量的autorelease對象導致內存激增,需要考慮手動創建autoreleasepool來釋放局部變量的情況!

所有權修飾符

__strong

持有強引用的變量會在超過其作用域的時候被釋放;對應屬性中的retain/strong;默認情況下的所有權修飾符是__strong;

 {
   // 自己生成并持有對象
   id _strong obj = [[NSObject alloc]init];
 }// 超出作用域,強引用失效,釋放對象  
__weak
  • __weak修飾符解決的是兩個強引用對象互相引用導致的引用循環所引發的內存泄露問題;
  • __weak修飾符與__strong 修飾符相反,不能持有對象;
  • __weak修飾符持有的對象對釋放后,弱引用會被自動置為nil;
{  
 id obj = [[NSObject alloc]init];
 id __weak weakObj = obj;   
} 
  • 首先會調用函數objc_loadWeakRetained(&obj);
  • retain一下obj;但不改變引用計數;
  • obj_autorealease()將obj注冊到autorealeasepool中;
  • 全局有一個可變字典;obj的內存地址作為key值,value是所有指向obj的weak指針列表(CFMutableSet);
  • obj指向的內存塊銷毀了,對應的value中指針都為統一置為nil
__unsafe_unretained

和weak相似但不會在對象被銷毀時自動置為nil(屬性中對應assgin)
對于weak來說__unsafe_unretained性能上更加優越

__autoreleasing

類似調用autorelease方法將對象添加到自動釋放池中

內存管理開發tips

ARC與Block的內存管理

block為什么會導致循環引用?
當self對象持有block,在block中也持有self;在block中會copy一個self對象作為block的一個屬性;當要該屬性的釋放要等到block從堆中移除,而此時block要等待持有自己的self銷毀,由此導致循環引用;
解決方法:弱化self對象,但要在block內不防止弱化的對象過早釋放,由此在block中還得再次強化已弱化的self對象

屬性的set方法MRC下的內存管理的寫法

 -(void)setName:(NSString*)newName{
   [newName retain];
   [_name release];
   _name = newName;  

自動釋放池和線程

Cocoa程序中的每一個線程,都維護自己的自動釋放池棧。如果你要寫一個Foundation程序,或者卸載一個線程,你需要創建自己的autorelease池塊。如果你的程序或者線程是常駐內存,并可能產生大量自動釋放對象,你應該使用自動釋放池(AppKit和UIKit在主線程中有自動釋放池);否則自動釋放對象累積,導致內存占用增長。如果你不是Cocoa中卸載線程,你不需要使用一個自動釋放池塊。

控制器移除時dealloc無法被調動

遇到這種情況,就需要排查控制器中出現的內存泄露了;

  • delegate屬性類型是否被聲明為strong
  • NSTime是否被被關閉
  • block中是否造成了self的循環引用
  • 是否存在兩個對象之間的強引用
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容