iOS關(guān)于內(nèi)存管理

在OC中對象是存儲在堆中的婿脸,系統(tǒng)并不會自動釋放堆中的內(nèi)存粱胜,如果一個對象創(chuàng)建并使用后沒有得到及時釋放那么就會占用大量內(nèi)存。其他高級語言如C#狐树、Java都是通過垃圾回收來(GC)解決這個問題的焙压,但在OjbC中并沒有類似的垃圾回收機制,因此它的內(nèi)存管理就需要由開發(fā)人員手動維護抑钟。

引用計數(shù)器

在Xcode4.0之后涯曲,引入了ARC(Automatic Reference Counting)機制,程序編譯時Xcode可以自動給你的代碼添加內(nèi)存釋放代碼,如果編寫手動釋放代碼Xcode會報錯在塔,因此在今天的內(nèi)容中如果你使用的是Xcode4.2之后的版本(相信現(xiàn)在大部分朋友用的版本都比這個要高)幻件,必須手動關(guān)閉ARC,這樣才有助于你理解ObjC的內(nèi)存回收機制蛔溃。

Xcode關(guān)閉ARC:選中工程—>Build Settings-->輸入garbage找到Objective-C Automatic Reference Counting設(shè)置為No

在ObjC中內(nèi)存的管理是依賴對象引用計數(shù)器來進行的:在ObjC中每個對象內(nèi)部都有一個與之對應(yīng)的整數(shù)(retainCount)绰沥,叫“引用計數(shù)器”,當一個對象在創(chuàng)建之后它的引用計數(shù)器為1贺待,當調(diào)用這個對象的alloc徽曲、retain、new麸塞、copy方法之后引用計數(shù)器自動在原來的基礎(chǔ)上加1(ObjC中調(diào)用一個對象的方法就是給這個對象發(fā)送一個消息)秃臣,當調(diào)用這個對象的release方法之后它的引用計數(shù)器減1,如果一個對象的引用計數(shù)器為0哪工,則系統(tǒng)會自動調(diào)用這個對象的dealloc方法來銷毀這個對象奥此。

代碼如下:

#import <Foundation/Foundation.h>
#import "Person.h"
void Test1(){
 Person *p=[[Person alloc]init]; //調(diào)用alloc弧哎,引用計數(shù)器+1 p.name=@"Kenshin"; p.age=28; 
NSLog(@"retainCount=%lu",[p retainCount]);
 //結(jié)果:
retainCount=1 [p release]; //結(jié)果:Invoke Person's dealloc method. 
//上面調(diào)用過release方法,p指向的對象就會被銷毀得院,但是此時變量p中還存放著Person對象的地址傻铣, 
//如果不設(shè)置p=nil,則p就是一個野指針祥绞,它指向的內(nèi)存已經(jīng)不屬于這個程序非洲,因此是很危險的 p=nil; 
//如果不設(shè)置p=nil,此時如果再調(diào)用對象release會報錯蜕径,但是如果此時p已經(jīng)是空指針了两踏, 
//則在ObjC中給空指針發(fā)送消息是不會報錯的 
[p release];
}

void Test2(){
 Person *p=[[Person alloc]init]; 
p.name=@"Kenshin";
 p.age=28;
 NSLog(@"retainCount=%lu",[p retainCount]); 
//結(jié)果:
retainCount=1 [p retain];//引用計數(shù)器+1
 NSLog(@"retainCount=%lu",[p retainCount]); 
//結(jié)果:
retainCount=2 [p release];//調(diào)用1次release引用計數(shù)器-1 NSLog(@"retainCount=%lu",[p retainCount]); 
//結(jié)果:
retainCount=1 [p release];
 //結(jié)果:Invoke Person's dealloc method. p=nil;
}
int main(int argc, const char * argv[]) {
 @autoreleasepool { 
Test1();
 } 
return 0;
}

注意:release會使引用計數(shù)減1,當引用計數(shù)為0的時候兜喻,系統(tǒng)會自動調(diào)用dealloc銷毀對象梦染,在對象release之后,需要將對象置nil朴皆,否則會成為野指針帕识,在OC中,對一個空的對象發(fā)送消息是不會引起錯誤的遂铡。

內(nèi)存釋放的原則就是:誰分配肮疗,誰釋放

自動釋放池

這只是一種半自動的機制,有些操作還是需要我們手動設(shè)置的扒接。自動內(nèi)存釋放使用@autoreleasepool關(guān)鍵字聲明一個代碼塊伪货,如果一個對象在初始化時調(diào)用了autorelase方法,那么當代碼塊執(zhí)行完之后钾怔,在塊中調(diào)用過autorelease方法的對象都會自動調(diào)用一次release方法碱呼。這樣一來就起到了自動釋放的作用,同時對象的銷毀過程也得到了延遲(統(tǒng)一調(diào)用release方法)宗侦。

代碼如下:

#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) { 
@autoreleasepool {
 Person *person1=[[Person alloc]init];
 [person1 autorelease];//調(diào)用了autorelease方法后面就不需要手動調(diào)用release方法了
 person1.name=@"Kenshin";//由于autorelease是延遲釋放愚臀,所以這里仍然可以使用
person1 Person *person2=[[[Person alloc]initWithName:@"Kaoru"] autorelease];//調(diào)用了autorelease方法 
Person *person3=[Person personWithName:@"rosa"];//內(nèi)部已經(jīng)調(diào)用了autorelease,所以不需要手動釋放矾利,這也符合內(nèi)存管理原則姑裂,因為這里并沒有alloc所以不需要release或者autorelease
 Person *person4=[Person personWithName:@"jack"];
 [person4 retain]; 
}
 /*結(jié)果:
 Invoke Person(rosa) dealloc method.
 Invoke Person(Kaoru) dealloc method. 
Invoke Person(Kenshin) dealloc method. 
*/ 
return 0;
}

對于自動內(nèi)存釋放簡單總結(jié)一下:

(1)autorelease方法不會改變對象的引用計數(shù)器,只是將這個對象放到自動釋放池中梦皮;
(2)自動釋放池實質(zhì)是當自動釋放池銷毀后調(diào)用對象的release方法炭分,不一定就能銷毀對象(例如如果一個對象的引用計數(shù)器>1則此時就無法銷毀);
(3)由于自動釋放池最后統(tǒng)一銷毀對象剑肯,因此如果一個操作比較占用內(nèi)存(對象比較多或者對象占用資源比較多)捧毛,最好不要放到自動釋放池或者考慮放到多個自動釋放池;
(4)ObjC中類庫中的靜態(tài)方法一般都不需要手動釋放,內(nèi)部已經(jīng)調(diào)用了autorelease方法呀忧;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末师痕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子而账,更是在濱河造成了極大的恐慌胰坟,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泞辐,死亡現(xiàn)場離奇詭異笔横,居然都是意外死亡,警方通過查閱死者的電腦和手機咐吼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門吹缔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锯茄,你說我怎么就攤上這事厢塘。” “怎么了肌幽?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵晚碾,是天一觀的道長。 經(jīng)常有香客問我喂急,道長格嘁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任煮岁,我火速辦了婚禮讥蔽,結(jié)果婚禮上涣易,老公的妹妹穿的比我還像新娘画机。我一直安慰自己,他們只是感情好新症,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布步氏。 她就那樣靜靜地躺著,像睡著了一般徒爹。 火紅的嫁衣襯著肌膚如雪荚醒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天隆嗅,我揣著相機與錄音界阁,去河邊找鬼。 笑死胖喳,一個胖子當著我的面吹牛泡躯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼较剃,長吁一口氣:“原來是場噩夢啊……” “哼咕别!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起写穴,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤惰拱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后啊送,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體偿短,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年馋没,在試婚紗的時候發(fā)現(xiàn)自己被綠了翔冀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡披泪,死狀恐怖纤子,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情款票,我是刑警寧澤控硼,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站艾少,受9級特大地震影響卡乾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜缚够,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一幔妨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谍椅,春花似錦误堡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至杖们,卻和暖如春悉抵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背摘完。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工姥饰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人孝治。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓列粪,卻偏偏與公主長得像栅螟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子篱竭,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

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