iOS內(nèi)存管理篇(一)---alloc/reatain/release/dealloc方法實(shí)現(xiàn)

前言:自從蘋果開發(fā)出 ARC這個(gè)后,基本上使用 MRC開發(fā)的就很少了它呀,但是我們還是有必要了解一下原理以及過去的使用。

1. MRC是什么

MRC(MannulReference Counting)簡(jiǎn)而言之就是手動(dòng)計(jì)數(shù)棒厘,手動(dòng)管理 對(duì)象的釋放以及引用計(jì)數(shù)

2. ARC是什么

ARC(Automatic Reference Counting) 自動(dòng)管理計(jì)數(shù)纵穿,不需要寫多余的代碼。

我們簡(jiǎn)單的來了解一下MRC的工作
現(xiàn)在我們來新建一個(gè)工程 并且在如圖的地方輸入 "-fno-objc-arc"

這里寫圖片描述

然后我們?cè)?appdelegate.m文件里面輸入如下的代碼

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    NSObject *object=[[NSObject alloc]init];
    ///這個(gè)時(shí)候 object 沒有被別的對(duì)象持有 僅僅調(diào)用了 [object retainCount] 方法 所以 object的引用計(jì)數(shù)為1
    NSLog(@"objectCount:%ld",[object retainCount]);
    
    NSObject *another=[object retain];
    ///這個(gè)時(shí)候 object 被 another 持有 所以引用計(jì)數(shù)+1 此時(shí)引用計(jì)數(shù)為 2
    NSLog(@"objectCount:%ld",[object retainCount]);
    
    [another release];
    ///執(zhí)行完[another release]這句代碼后 another 的被釋放 所以 object 的引用計(jì)數(shù)變成1了
    NSLog(@"objectCount:%ld",[object retainCount]);
    
    ///執(zhí)行完這句代碼后, object 引用計(jì)數(shù)就為0了
    [object release];
    return YES;
}

輸出結(jié)果如下:

這里寫圖片描述

我們通過這個(gè)例子可以看出來,對(duì)于 MRC來說,需要手動(dòng)維護(hù)對(duì)象的計(jì)數(shù),管理對(duì)象的存在和銷毀的問題.如果稍有不注意的地方,就會(huì)存在內(nèi)存泄露和循環(huán)引用的問題,那么蘋果為了避免這一套繁瑣的開發(fā)任務(wù),方便開發(fā)者去更好的進(jìn)行開發(fā)任務(wù),于是開發(fā)出了一套 ARC,這是我們今天重點(diǎn)學(xué)習(xí)的內(nèi)容

在此之前,我們需要很好的了解什么引用計(jì)數(shù):

一個(gè)對(duì)象被持有的數(shù)量,打個(gè)比方來說,有一根繩子,沒有人握住的時(shí)候,引用計(jì)數(shù)是0,當(dāng)1個(gè)人握住的時(shí)候 引用計(jì)數(shù)+1 ,往后每疊加一個(gè)人,引用計(jì)數(shù)變依次+1,當(dāng)有一個(gè)人松手的時(shí)候引用計(jì)數(shù)-1,直到?jīng)]有繩子沒有人握住的時(shí)候,繩子掉下來 銷毀了,這就是引用計(jì)數(shù)的概念.

所以引用計(jì)數(shù)的管理方法是

每個(gè)對(duì)象都有一個(gè)與之關(guān)聯(lián)的整數(shù),這個(gè)整數(shù)被稱為引用計(jì)數(shù),在Objective-C中,通過不同的方法可以對(duì)引用計(jì)數(shù)進(jìn)行操作,具體的處理如下表:
| 對(duì)象操作 | Objective-C方法 | 對(duì)應(yīng)的操作結(jié)果 |
| ------------- |:-------------|: -----|
| 生成并持有對(duì)象 | alloc, new, copy,mutableCopy等方法 | 生成對(duì)象并設(shè)置引用計(jì)數(shù) =1 |
| 持有對(duì)象 | reatain方法 | 使引用計(jì)數(shù) +1 |
| 釋放對(duì)象 | release方法 | 使引用計(jì)數(shù) -1 |
| 廢棄對(duì)象 | dealloc方法---系統(tǒng)自動(dòng)調(diào)用 | 引用計(jì)數(shù) =0 時(shí)調(diào)用 |

來講一下 alloc/reatain/release/dealloc方法的實(shí)現(xiàn)

  1. alloc
    我們看一下 alloc 如何實(shí)現(xiàn)的

    +(id)alloc
    

{
return [self allocWithZone:NSDefaultMallocZone()];
}
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
return NSAllocateObject(self, 0, zone);
}
```
通過allocWithZone類方法調(diào)用 NSAllocateObject方法來開辟了一塊內(nèi)存空間,我們來看一下NSAllocateObject方法是如何實(shí)現(xiàn)的

struct obj_layout{
    NSUInteger retained;
};

inline id
NSAllocateObject(Class  _Nonnull aClass, NSUInteger extraBytes, NSZone * _Nullable zone)
{
    int size = 計(jì)算容納對(duì)象所需要的內(nèi)存大小
    id new = NSZoneMalloc(zone, size);
    memset(new,0,size);
    new = (id)&((struct obj_layout *)new)[1];
    
}

NSAllocateObject通過調(diào)用NSZoneMalloc函數(shù)分配存放對(duì)象所需要的內(nèi)存控件,之后將該內(nèi)存空間置0,最后返回作為對(duì)象而使用的指針

我們可以執(zhí)行一下如下代碼

    id obj = [[NSObject alloc]init];
    NSLog(@"retainCount = %lu",(unsigned long)[obj retainCount]);

執(zhí)行結(jié)果為:

2017-06-28 18:15:04.009 MRCTest[12244:1459486] retainCount = 1

reatian 和 release 的方法剛剛在 MRC已經(jīng)看過 我們看一下 dealloc 方法

-(void)dealloc
{
    NSDeallocateObject(self);
}

inline void
NSDeallocateObject(id  _Nonnull object)
{
    struct obj_layout *o = ((struct obj_layout*) anObject)[-1];
    free(o);
}

每個(gè)對(duì)象都具備 dealloc 方法,當(dāng)一個(gè)對(duì)象的引用計(jì)數(shù)為0的時(shí)候,也就意味著沒有任何地方需要該對(duì)象,系統(tǒng)會(huì)自動(dòng)回收對(duì)該對(duì)象所占用的內(nèi)存,在系統(tǒng)銷毀對(duì)象的時(shí)候,會(huì)自動(dòng)調(diào)用該對(duì)象的 dealloc 方法來執(zhí)行一些回收的操作,如果此時(shí)該對(duì)象還對(duì)其他對(duì)象有引用的話,那么就需要重寫 dealloc 方法來釋放該對(duì)象對(duì)其他對(duì)象的引用 以確保該對(duì)象能正常釋放銷毀

如何重寫 dealloc 方法

 - (void)dealloc {

    // 處理該對(duì)象的其他引用(通過release方法)
    
    /** 回調(diào)父類的dealloc方法 */
    [super dealloc];
}

對(duì)于alloc/reatain/release/dealloc可以總結(jié)如下:

  • 在 Objective-C的對(duì)象中存有引用計(jì)數(shù)這一整數(shù)值
  • 調(diào)用 alloc或者是 retain 方法后,引用計(jì)數(shù)值加1
  • 調(diào)用 release 后,引用計(jì)數(shù)值減1
  • 引用計(jì)數(shù)為0時(shí),調(diào)用 dealloc 方法銷毀此對(duì)象

蘋果對(duì)這四個(gè)方法的使用

  • alloc

    +alloc
    +allocWithZone: 
    class_createInstance        //此方法可以通過objc4中的runtime/objc-runtime-new.mm確認(rèn)
    calloc                      // 分配內(nèi)存塊
    
  • retainCount

-retainCount 
__CFDoExternRefOperation    // 此函數(shù)根據(jù)retain,retainCount,release操作進(jìn)行分發(fā),調(diào)用__CFBasicHashXXX方法
CFBasicHashGetCountOfKey
  • retain
-retain
__CFDoExternRefOperation 
CFBasicHashAddValue
  • release
__CFDoExternRefOperation 
CFBasicHashRemoveValue      // 當(dāng)此函數(shù)返回0時(shí), -release調(diào)用dealloc方法

可以從__CFDoExternRefOperation函數(shù)以及由此函數(shù)調(diào)用的哥哥函數(shù)名來看,蘋果的實(shí)現(xiàn)大概就是采用的引用計(jì)數(shù)表來管理引用計(jì)數(shù)的

如圖


這里寫圖片描述

好了今天這幾個(gè)方法就講到這里,明天我們將來學(xué)習(xí)一下AutoreleasePool

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奢人,一起剝皮案震驚了整個(gè)濱河市谓媒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌达传,老刑警劉巖篙耗,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異宪赶,居然都是意外死亡宗弯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門搂妻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蒙保,“玉大人,你說我怎么就攤上這事欲主〉瞬蓿” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵扁瓢,是天一觀的道長(zhǎng)详恼。 經(jīng)常有香客問我,道長(zhǎng)引几,這世上最難降的妖魔是什么昧互? 我笑而不...
    開封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮伟桅,結(jié)果婚禮上敞掘,老公的妹妹穿的比我還像新娘。我一直安慰自己楣铁,他們只是感情好玖雁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盖腕,像睡著了一般赫冬。 火紅的嫁衣襯著肌膚如雪浓镜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天劲厌,我揣著相機(jī)與錄音竖哩,去河邊找鬼。 笑死脊僚,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的遵绰。 我是一名探鬼主播辽幌,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼椿访!你這毒婦竟也來了乌企?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤成玫,失蹤者是張志新(化名)和其女友劉穎加酵,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哭当,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡猪腕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钦勘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陋葡。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖彻采,靈堂內(nèi)的尸體忽然破棺而出腐缤,到底是詐尸還是另有隱情,我是刑警寧澤肛响,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布岭粤,位于F島的核電站,受9級(jí)特大地震影響特笋,放射性物質(zhì)發(fā)生泄漏剃浇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一雹有、第九天 我趴在偏房一處隱蔽的房頂上張望偿渡。 院中可真熱鬧,春花似錦霸奕、人聲如沸溜宽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽适揉。三九已至留攒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嫉嘀,已是汗流浹背炼邀。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剪侮,地道東北人拭宁。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瓣俯,于是被迫代替她去往敵國(guó)和親杰标。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

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