04內(nèi)存管理

4.1 手動管理

  • 自己生成的對象自己持有,可以調(diào)用release方法減少retain數(shù)量。
  • 非自己生成的對象也可以持有后室,通過調(diào)用retain方法可以持有對象砚哆,引用數(shù)+1独撇。
  • 不再需要自己持有的對象要及時釋放,注意類中的property要在- (void)dealloc方法中賦值nil躁锁,這樣寫相當(dāng)于release了纷铣。
- (void)dealloc
{
    self.arr = nil;
    [super dealloc];
}
  • 無法釋放非自己持有的對象,注意當(dāng)一個變量持有一次對象后战转,只能釋放一次关炼。也就是說retainCount必須+1和-1對稱。

  • alloc的實現(xiàn)匣吊。其實就是調(diào)用calloc方法申請內(nèi)存和C語言的差不多儒拂,只不過對象的頭部位有個地址用于存儲引用數(shù)。而retain色鸳、release就是對引用數(shù)加減社痛,dealloc則是free掉對象。

4.2 Autorelease

  • autorelease這個玩意本質(zhì)上是將對象加入到最近的一個NSAutoreleasePool中命雀,當(dāng)NSAutoreleasePool銷毀時會將對象release蒜哀。因此這里就有個坑了,如果這個pool很久都不銷毀吏砂,里面的對象就始終存在撵儿,有可能會造成內(nèi)存不足。
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

// 當(dāng)調(diào)用autorelease方法時狐血,其實是將對象obj放到了pool的一個對象列表中
NSObject* obj = [[[NSObject alloc] init] autorelease];

[pool drain]; // obj會被調(diào)用release方法

  • 注意到main.m中有這樣的代碼淀歇,在最外層就有個autoreleasepool了。
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

4.3 ARC

  • 我的理解

所謂ARC是通過編譯器和運行時的協(xié)作來實現(xiàn)自動管理引用計數(shù)匈织,編譯器在ARC有效的代碼中加入額外的代碼來加減引用計數(shù)浪默。

  • 標(biāo)識

    1. __strong:默認(rèn)就是
    2. __weak:需顯式使用
    3. __autoreleasing:這個標(biāo)識一些情況下是不需要顯式使用,一些情況下是不需要的缀匕,最為致命纳决。
    4. __unsafe_unretained:個人感覺已經(jīng)被棄用了,在沒有weak的時代使用的東西乡小。
  • __strong

這個修飾符具有持有對象的功能阔加,與retain類似。它的使用分為如下幾種情況:
1满钟、id __strong obj = [[NSObject alloc] init]; 這行代碼可以理解為如下代碼胜榔,可見所謂自動管理胳喷,就是在編譯出來的代碼中對強(qiáng)引用變量調(diào)用release方法。

id obj = objc_msgSend(NSObject, @selector(alloc));

objc_msgSend(obj, @selector(init));
objc_release(obj);


2苗分、`id __strong obj = [NSMutableArray array];` 這行代碼可以理解為以下代碼厌蔽,很有意思的代碼。objc_retainAutoreleasedReturnValue是持有(retain)了一個在autoreleasepool中的對象,而這個對象就是array方法的返回值摔癣。

id obj = objc_msgSend(NSMutableArray, @selector(array));
objc_retainAutoreleasedReturnValue(obj);
objc_release(obj); // 離開作用域后自動釋放


與`objc_retainAutoreleasedReturnValue`成對出現(xiàn)的是這個方法`objc_autoreleasedReturnValue`方法奴饮,對于NSMutableArray類的array方法可能是這樣實現(xiàn)的
  • (id)array
    {
    return [[NSMutableArray alloc] init];
    }

它可以理解為如下代碼

  • (id)array
    {
    id obj = objc_msgSend(NSMutableArray, @selector(alloc));
    objc_msgSend(obj, @selector(init));
    return objc_autoreleasedReturnValue(obj);
    }

<font color=green>對于外界調(diào)用這個方法賦值的變量來說,只是在使用一個autoreleasepool中的對象择浊。在結(jié)合`objc_retainAutoreleasedReturnValue`使用時戴卜,其實生成的對象并沒有進(jìn)入autoreleasepool,而是直接傳遞給了使用`objc_retainAutoreleasedReturnValue`方法賦值的變量琢岩。</font>
  • __weak

    1投剥、被__weak修飾的<font color=green>變量的地址</font>會被放入到weak表中,這個表是個k-v形式的担孔,key是對象的地址江锨,value是所有引用了這個對象的變量的地址。

    2糕篇、一個對象被釋放的過程是個復(fù)雜的過程啄育,

    objc_release -> dealloc(如果引用計數(shù)為0) -> _objc_rootDealloc 
    -> object_dispose -> objc_destructInstance 
    -> objc_clear_deallocating
    {
      1、用對象地址找到weak表中的value
      2拌消、所有變量(weak表中記錄了地址)賦值nil
      3挑豌、從weak表刪除記錄
      4、從引用計數(shù)表刪除廢棄對象的地址為鍵值的記錄
    } 
    
    從以上的過程可以看出當(dāng)對象被銷毀后所有引用它的__weak變量都會被賦值為nil墩崩,這個過程是比較消耗CPU的氓英,少用。
    
    3鹦筹、<font color=green>**使用被__weak修飾的變量就是使用注冊到autoreleasepool中的對象**</font>铝阐,從以下代碼來進(jìn)行理解這句話,
    
    id __weak obj1 = obj;
    NSLog(@"%@", obj1);
    
    這句話會大致被編譯器翻譯成這樣
    

    id obj盛龄;
    objc_initWeak(&obj1, obj);
    id tmp = objc_loadWeakRetaind(&obj1);
    objc_autorelease(tmp);
    NSLog(@"%@", tmp);
    objc_destroyWeak(&obj1);

    可以看到為了能夠NSLog執(zhí)行時obj1引用的對象不被銷毀饰迹,需要將它賦值給一個strong(默認(rèn))修飾的臨時變量,而這個臨時變量需要放到autoreleasepool中余舶,因此存在一個問題,當(dāng)你多次在一個作用域中多次使用weak修飾的變量锹淌,會導(dǎo)致很多臨時變量產(chǎn)生而且會放到autoreleasepool中匿值,作用域結(jié)束后autoreleasepool有很多工作要做。所以少用weak赂摆,一般就是避免循環(huán)引用挟憔。

  • __autoreleasing钟些,核心就是把修飾的變量放入到autoreleasepool中,沒啥多說的绊谭。

  • 注意事項:

    1. 不能使用retain政恍、release、retainCount达传、autorelease這樣方法
    2. 不能使用NSAllocateObject和NSDeallocateObject方法篙耗,實際上我根本沒用過。
    3. 需要在函數(shù)命名時遵守規(guī)則宪赶,比如alloc\new\copy\mutableCopy必須給與調(diào)用者對象持有權(quán)限宗弯。
    4. 不能使用NSAutoreleasePool,可以用@autoreleasepool替換搂妻。
    5. dealloc方法不能顯示調(diào)用蒙保,很明顯的例子就是在MRC中寫dealloc方法時一定要調(diào)用super的dealloc方法,但是在ARC中不行了欲主,不過notificationCenter的刪除等處理還是要寫在dealloc方法中的邓厕,會自動調(diào)用。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扁瓢,一起剝皮案震驚了整個濱河市详恼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涤妒,老刑警劉巖单雾,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異她紫,居然都是意外死亡硅堆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門贿讹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渐逃,“玉大人,你說我怎么就攤上這事民褂∏丫眨” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵赊堪,是天一觀的道長面殖。 經(jīng)常有香客問我,道長哭廉,這世上最難降的妖魔是什么脊僚? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮遵绰,結(jié)果婚禮上辽幌,老公的妹妹穿的比我還像新娘增淹。我一直安慰自己,他們只是感情好乌企,可當(dāng)我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布虑润。 她就那樣靜靜地躺著,像睡著了一般加酵。 火紅的嫁衣襯著肌膚如雪拳喻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天虽画,我揣著相機(jī)與錄音舞蔽,去河邊找鬼。 笑死码撰,一個胖子當(dāng)著我的面吹牛渗柿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播脖岛,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼朵栖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了柴梆?” 一聲冷哼從身側(cè)響起陨溅,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绍在,沒想到半個月后门扇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡偿渡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年臼寄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溜宽。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡吉拳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出适揉,到底是詐尸還是另有隱情留攒,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布嫉嘀,位于F島的核電站炼邀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏剪侮。R本人自食惡果不足惜汤善,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望票彪。 院中可真熱鬧红淡,春花似錦、人聲如沸降铸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽推掸。三九已至桶蝎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谅畅,已是汗流浹背登渣。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留毡泻,地道東北人胜茧。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像仇味,于是被迫代替她去往敵國和親呻顽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容