內(nèi)存管理

一.基本介紹(先創(chuàng)建一個空工程待用)

1)為什么要管理內(nèi)存?

   因為手機內(nèi)存大小有限,如果有內(nèi)存分配但是不釋放它,哪怕這塊內(nèi)存已經(jīng)不用了.導(dǎo)致你的應(yīng)用程序占用越來越多的內(nèi)存,并導(dǎo)致整體性能下降,或者直接在真機上閃退.因此需要把不必要的內(nèi)存空間給釋放掉.

2)OC內(nèi)存管理的三種方式

Objective-C提供了三種內(nèi)存管理方式:
    1)manual reference counting(MRC,手動管理)
    2)automatic reference counting(ARC,自動引用計數(shù))
    3)garbage collection(GC,垃圾回收).OS X 10.8(山獅)被廢棄,使用ARC
   IOS不支持垃圾回收雾袱;ARC作為蘋果,在XCode4.2以后(IOS5)新提供的技術(shù),蘋果推薦開發(fā)者使用ARC技術(shù)來管理內(nèi)存穗慕;但是我們從手動管理開始學(xué)起.

3)新創(chuàng)建的工程默認都是ARC(自動管理),修改為手動管理

1)選中藍色的項目工程文件
2)中間部分找到build settings選項
3)搜索gar,把那個選項改為NO

4). 怎么知道創(chuàng)建的對象被釋放?(畫圖來說明:人和牛的例子)

   每個OC的對象都具備一個屬性叫做retainCount(該對象被多少個人套住,有多少人在使用),如果這個屬性>=1,意味著至少有一個人再使用,只有當(dāng)retainCount變?yōu)?,蘋果自動釋放

testOne:
    People * zhangSan = [[People alloc]init];
    NSLog(@"1樱蛤、引用計數(shù) = %d",zhangSan.retainCount);
    [zhangSan release];
    NSLog(@“2渣玲、引用計數(shù) = %d",zhangSan.retainCount);
    
    //重寫People的dealloc方法,證明被釋放
    -(void)dealloc{
        NSLog(@"Invoke Person's dealloc method.”);
        [super dealloc];
        //注意最后一定要調(diào)用父類的dealloc方法(兩個目的:一是父類可能有其他引用對象需要釋放稿茉;二是:當(dāng)前對象真正的釋放操作是在super的dealloc中完成的)
    }
總結(jié)
    1.alloc/new會導(dǎo)致引用計數(shù)+1
    2.release  會導(dǎo)致引用計數(shù)-1
    3.對象在使用完成之后不會自動銷毀,如果不釋放會內(nèi)存泄露
    4.已經(jīng)釋放的數(shù)據(jù)再次使用/釋放(過度釋放)會崩潰,通常會出現(xiàn)Thread 1:EXC_BAD_ACCESS
    '(code=EXC_I386_GPFLT)錯誤,這是野指針錯誤,因為你訪問了一塊已經(jīng)不屬于你的內(nèi)存
        解決辦法:[obj release]; obj = nil;因為給空對象發(fā)送消息是不會引起錯誤的
    5.對象被釋放的時候會調(diào)用自己類的delloc方法
testTwo:
    People * zhangSan = [[People alloc]init];
    NSLog(@"1遍坟、引用計數(shù) = %d",zhangSan.retainCount);
    [zhangSan retain];
    NSLog(@"2、引用計數(shù) = %d",zhangSan.retainCount);
    [zhangSan retain];
    NSLog(@"3资盅、引用計數(shù) = %d",zhangSan.retainCount);
    [zhangSan release];//alloc
    [zhangSan release];//retain
    [zhangSan release];//retain
總結(jié):
    1.retain會導(dǎo)致引用計數(shù)+1
    2.誰創(chuàng)建誰釋放,誰使用誰管理
    3.引用計數(shù)+1的操作稱為”擁有take ownership of”,-1的操作稱為”放棄relinquish”,只有在擁有對象的時候才可以放心的使用,當(dāng)它被所有人放棄的時候Objective-C運行環(huán)境會自動回收這個對象
testThree(給People類擴充一個myLabel屬性,一個age屬性)
    People * p = [People new];
    UILabel * a = [UILabel new];
    NSLog(@"a 的引用計數(shù)為”,a.retainCount);
    p.myLabel = a;
    NSLog(@"a 的引用計數(shù)為”,a.retainCount);
    [a release];
    NSLog(@"a 的引用計數(shù)為”,a.retainCount);
    [p release];
    
總結(jié):
    1.給屬性賦值,會導(dǎo)致引用計數(shù)+1
    2.對于類中聲明的屬性一般在delloc方法中釋放,釋放后記得=nil
    3.對于assign修飾的屬性不需要內(nèi)存管理,因為內(nèi)存管理是針對于對象的.
testFour:
    People * p1 = [People new];
    People * p2 = p1;
    NSLog(@"p1的引用計數(shù)為”,p1.retainCount);
    NSLog(@"p2的引用計數(shù)為”,p2.retainCount);
    [p1 retain];
    NSLog(@"p1的引用計數(shù)為”,p1.retainCount);
    NSLog(@"p2的引用計數(shù)為”,p2.retainCount);
    
結(jié)論:
    1.指針賦值不會讓引用計數(shù)+1
    2.p2的引用計數(shù)等于p1的,p1改p2也改

testOne
    UILabel * label = [UILabel new];
    NSLog(@"label的引用計數(shù)為”, label.retainCount);
    [self.window addSubView:label];
    NSLog(@"label的引用計數(shù)為”, label.retainCount);
    [label release];

結(jié)論:
    1.addSubView會導(dǎo)致引用計數(shù)+1,因為它被self.window擁有,遵循誰擁有誰管理原則,它內(nèi)部會自己處理內(nèi)存問題,不用我們釋放
    2.什么時候release?當(dāng)你確定該對象不會被使用了,就可以release,一般寫在最后.
testTwo(脫兩個xib控件并且綁定對象)
    NSLog(@"a %d”,a.retainCount);
    NSLog(@"b %d”,b.retainCount);
    
結(jié)論:
    1.通過拖拽xib,引用計數(shù)+1,原理同結(jié)論1,而且系統(tǒng)會在delloc中自己釋放
    2.全局變量一般在delloc中釋放,局部變量用完就release
    3.一般來說,區(qū)間1和區(qū)間2的對象屬性都在delloc方法中釋放
testThree
    -(void)textFout {
        UILabel * label = [[self createLabel] retain];
        [label release];
        label = nil;
    }
    -(UILabel *)createUILabel {
        UILabel * label = [UILabel new];
        ******做一些其他事情*****
        return [label autorelease];
    }
結(jié)論
    1.autorelease自動釋放
        * 對象執(zhí)行autorelease方法時會將對象添加到自動釋放池(autorelease pool)中
        * 當(dāng)自動釋放池銷毀時自動釋放池中所有對象作release操作,如果引用計數(shù)變?yōu)?就釋放
    2.一般來說,如果方法最后要返回一個對象,一般需要使用autorelease去釋放
    3.release 和 autorelease 的區(qū)別?
        * 如果能確定,使用release
        * 不能確定,使用autorelease
    注:autorelease不是隨便用的
        * 操作占用內(nèi)存比較大的對象的時候不要隨便使用,擔(dān)心對象釋放的時間太遲,可能會泄露
        * 操作占用內(nèi)存比較小的對象可以使用
        * 自動釋放池存儲于內(nèi)存中的棧中遵循"先進后出”原則
        * 自動釋放池實質(zhì)是當(dāng)自動釋放池銷毀后調(diào)用對象的release方法,不一定就能銷毀對象(例如如果一個對象的引用計數(shù)器>1則此時就無法銷毀)
testFour
    UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
    NSLog(@“btn",btn.retainCount);
    NSString * name = @"zhanSan";
    NSLog(@" name",name.retainCount);
    NSString * name1 = [NSString stringWithFormat:@“zhangSan"];
    NSLog(@" name",name.retainCount);
結(jié)論:
    1.ObjC中類庫中的+號方法(靜態(tài)方法)創(chuàng)建對象一般都不需要手動釋放,內(nèi)部已經(jīng)調(diào)用了autorelease方法;
    2.字符串是一個比較特殊的對象,但是只要人為+1,就要人為-1
testFive
    UILabel * label = [UILabel new];
    NSLog(@"%d",label.retainCount);
    NSArray * array = [NSArray arrayWithObjects:label,label, nil];
    NSLog(@"array:%d",array.retainCount);
    NSLog(@"%d",label.retainCount);
    [label release];//new
結(jié)論:
    1.數(shù)組的addObject會讓對象的引用計數(shù)+1.
    數(shù)組在釋放的時候,會對里面的對象執(zhí)行release,所以不用我們管.
testSix
    導(dǎo)航傳值導(dǎo)致引用計數(shù)+1
    界面?zhèn)髦等菀壮鲥e(記得全局變量到delloc中釋放)
* _oneArray     = [array retain];
* self.oneArray = array;
test.png
   @property的參數(shù)分為三類调榄,也就是說參數(shù)最多可以有三個,中間用逗號分隔呵扛,每類參數(shù)可以從上表三類參數(shù)中人選一個每庆。如果不進行設(shè)置或者只設(shè)置其中一類參數(shù),程序會使用三類中的各個默認參數(shù)今穿,默認參數(shù):(atomic,readwrite,assign)
一般情況下如果在多線程開發(fā)中一個屬性可能會被兩個及兩個以上的線程同時訪問缤灵,此時可以考慮atomic屬性,否則建議使用nonatomic蓝晒,不加鎖腮出,效率較高;readwirte方法會生成getter芝薇、setter兩個方法胚嘲,如果使用readonly則只生成getter方法;關(guān)于set方法處理需要特別說明洛二,假設(shè)我們定義一個屬性a馋劈,這里列出三種方式的生成代碼:

assign,用于基本數(shù)據(jù)類型
-(void)setA:(int)a{
    _a=a;
}

retain晾嘶,通常用于非字符串對象
-(void)setA:(Car *)a{
    if(_a!=a){
        [_a release];
        _a=[a retain];
    }
}

copy妓雾,通常用于字符串對象
-(void)setA:(NSString *)a{
    if(_a!=a){
        [_a release];
        _a=[a copy];
    }
}
內(nèi)存測試
    NSArray * array1 = [NSArray arrayWithObjects:@"1", nil];
    self.array4 = array1;
    NSArray * array2 = [[NSArray alloc] initWithObjects:@"array1",array1, nil];
    self.array4 = array2;
    NSArray * array3 = [NSArray arrayWithObjects:array1,array2, nil];
    self.array4 = array3;
    //3--2--2--2
內(nèi)存管理的知識點
    1.讓對象引用計數(shù)增加的9個操作
    alloc,new,copy,retain,addSubView,addObject,push,對象打點屬性賦值,控件關(guān)聯(lián)xib
    2.引用計數(shù)減少的兩個操作
    release  autorelease
    3.要保證讓對象引用計數(shù)增加的關(guān)鍵字跟讓對象引用計數(shù)減少的關(guān)鍵字 配對
    4.全局變量或者屬性在dealloc中釋放,局部變量在確定不使用以后就要釋放
    5.使用+號方法(靜態(tài)方法)創(chuàng)建的對象不需要管理內(nèi)存,內(nèi)部自動-1
    6.在方法中創(chuàng)建的對象如果要返回需要使用autorelease,在使用的時候手動retain
    7.全局對象變量在初始化的時候一般使用-號方法創(chuàng)建,使用+號方法創(chuàng)建需要手動retain,使用字面量創(chuàng)建需要手動retain
    8.分線程中的所有代碼都用@autorelease括起來,防止內(nèi)存泄露
    9.對象在釋放的時候除了[obj release];以外,為了安全起見,加上obj=nil;
    10.屬性直接self.obj = nil;即可,相當(dāng)于[obj release];obj=nil;  
ARC和MRC的關(guān)系
    ARC是編譯器特性,不是運行時特性.簡單說就是代碼在編譯的時候自動加入了retain/release/autorelease,原先需要手動添加的用來處理內(nèi)存管理的引用計數(shù)的代碼可以自動地由編譯器完成了.因此ARC和MRC性能是一樣的,有些時候還能更快,因為編譯器還可以執(zhí)行某些優(yōu)化
內(nèi)存管理的小技巧
    1)利用你靜態(tài)分析工具讓系統(tǒng)自動檢測內(nèi)存泄露的代碼(只能檢測一部分)
    1.選中項目工程文件
    2.中間部分,選擇藍色的project
    3.選中build settings,搜索Analyze During
    4.把Analyze During ’Build’修改為YES
    2)
      strong           weak
      retain,copy      assign
      strong:強引用,只要對象有人在用就不會被釋放掉
      weak:弱引用,并不是對象的真正的擁有者,如果對象被釋放,指針自動置為nil
      為了方便釋放對象,定義一個簡單的宏定義
      #define Release(obj) [obj release];obj=nil;
循環(huán)引用
    1.定時器導(dǎo)致的循環(huán)引用
    定時器在內(nèi)部會引用self,導(dǎo)致self在釋放的時候并不會釋放掉,因此在釋放對象之前需要先把定時器給關(guān)閉掉.釋放的代碼[_timer invalidate];_timer = nil;在delloc方法中調(diào)用無效,一般在viewDidDisappear中關(guān)閉定時器.
    2.代理導(dǎo)致的循環(huán)引用 A,B,C
    在A中創(chuàng)建B和C,引用計數(shù)分別為:A1,B1,A.delegate = B,引用計數(shù)變?yōu)?A1,B2.如果A釋放,B釋放,那么B變?yōu)锳,導(dǎo)致A.delegate也是1,所以A釋放不掉,B也沒釋放掉.
    解決辦法就是:delegate用assign修飾
    3.block導(dǎo)致的循環(huán)引用
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市垒迂,隨后出現(xiàn)的幾起案子械姻,更是在濱河造成了極大的恐慌,老刑警劉巖机断,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件楷拳,死亡現(xiàn)場離奇詭異材部,居然都是意外死亡,警方通過查閱死者的電腦和手機唯竹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來苦丁,“玉大人浸颓,你說我怎么就攤上這事⊥” “怎么了产上?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蛾狗。 經(jīng)常有香客問我晋涣,道長,這世上最難降的妖魔是什么沉桌? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任谢鹊,我火速辦了婚禮,結(jié)果婚禮上留凭,老公的妹妹穿的比我還像新娘佃扼。我一直安慰自己,他們只是感情好蔼夜,可當(dāng)我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布兼耀。 她就那樣靜靜地躺著,像睡著了一般求冷。 火紅的嫁衣襯著肌膚如雪瘤运。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天匠题,我揣著相機與錄音拯坟,去河邊找鬼。 笑死梧躺,一個胖子當(dāng)著我的面吹牛似谁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掠哥,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼巩踏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了续搀?” 一聲冷哼從身側(cè)響起塞琼,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎禁舷,沒想到半個月后彪杉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毅往,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年派近,在試婚紗的時候發(fā)現(xiàn)自己被綠了攀唯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡渴丸,死狀恐怖侯嘀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谱轨,我是刑警寧澤戒幔,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站土童,受9級特大地震影響诗茎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜献汗,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一敢订、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧雀瓢,春花似錦枢析、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至泊业,卻和暖如春把沼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吁伺。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工饮睬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人篮奄。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓捆愁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親窟却。 傳聞我的和親對象是個殘疾皇子昼丑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,515評論 2 359

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

  • 內(nèi)存管理 簡述OC中內(nèi)存管理機制。與retain配對使用的方法是dealloc還是release夸赫,為什么菩帝?需要與a...
    丶逐漸閱讀 1,971評論 1 16
  • There is something inside ,that they can't get to , that ...
    東了個尼閱讀 1,067評論 0 4
  • 為什么進行內(nèi)存管理? 由于移動設(shè)備的內(nèi)存極其有限,所以每個APP所占的內(nèi)存也是有限制的呼奢,當(dāng)app所占用的內(nèi)存較多時...
    天天想念閱讀 898評論 1 7
  • iOS內(nèi)存管理 概述 什么是內(nèi)存管理 應(yīng)用程序內(nèi)存管理是在程序運行時分配內(nèi)存(比如創(chuàng)建一個對象,會增加內(nèi)存占用)與...
    蚊香醬閱讀 5,728評論 8 119
  • 11.看下面的程序,第一個NSLog會輸出什么宜雀?這時str的retainCount是多少?第二個和第三個呢握础? 為什...
    AlanGe閱讀 730評論 1 4