IOS內存管理學習筆記

  內存管理做爲iOS中很是重要的部分,每個iOS開發者都應該深刻了解iOS內存管理,最近在學習iOS中整理出了一些知識點,先從MRC開始提及。數組

  1.當一個對象在建立以後它的引用計數器爲1,當調用這個對象的alloc、retain、new、copy方法以後引用計數器自動在原來的基礎上加1(ObjC中調用一個對象的方法就是給這個對象發送一個消息),當調用這個對象的release方法以後它的引用計數器減1,若是一個對象的引用計數器爲0,則系統會自動調用這個對象的dealloc方法來銷燬這個對象。安全

 

  2.@property的參數能夠分爲三類,也就是說最多能夠有三個參數,參數的含義以下表:框架

  

參數類型學習

參數名atom

參數含義spa

原子性線程

atomiccode

對屬性加鎖,線程安全,默認屬性orm

nonatomic對象

不加鎖,非線程安全

讀寫屬性

readonly

生成gettersetter方法,默認屬性

readwrite

只生成getter方法

set方法處理

assign

直接賦值,默認值

retain

release原來的值,再retain新值

copy

release原來的值,再copy新值

  各類屬性對應的setter方法內容以下:

assign, 一般用於基本數據類型,如:int,float

-(void)setA:(int)a{
    _a=a;
}

retain,一般用於非字符串對象

-(void)setA:(A *)a{
    if(_a!=a){
        [_a release];
        _a=[a retain];
    }
}

copy,一般用於字符串對象,block,NSArray,NSDictionary

-(void)setA:(NSString *)a{
    if(_a!=a){
        [_a release];
        _a=[a copy];
    }
}

3. 當使用手動引用計數的時候,Fundation框架中的一些方法可能會增長對象的引用計數,好比NSMutableArray中的addObject或者UIView中的addSubview,有一些方法將會減小對象的引用計數好比上面兩個接口對應的removeObjectAtIndex和removeFromSuperview。

 

4.再建立對象的時候推薦使用[[className alloc]init]而不是[className new],由於若是使用[className new],內部是調用的init方法初始化,咱們就無法調用initWithFrame之類的方法。

 

5.alloc:對象分配後引用計數爲1,retain:對象的引用計數+1,copy:開闢新的內存存放新對象,引用計數爲1,原對象引用計數不變。

 

6.給對象發送release消息並不必定會銷燬這個對象,而是將對象的引用計數-1,若是對象的引用計數爲0的話,對象就會被銷燬。而後系統會發送dealloc消息給這個對象釋放它的內存。

 

7.對使用了retain、copy、mutableCopy、alloc、new方法的任何對象,以及具備retain和copy特性的屬性進行釋放,須要覆蓋dealloc方法,使得在對象被釋放的時候可以釋放這些實例變量。

 

8.NSAutoreleasePool內部包含一個數組(NSMutableArray),用來保存聲明爲autorelease的全部對象。若是一個對象聲明爲autorelease,系統所作的工做就是把這個對象加入到這個數組中去。

ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1,把此對象加入autorelease pool中

NSAutoreleasePool自身在銷燬的時候,會遍歷一遍這個數組,release數組中的每一個成員。若是此時數組中成員的retain count爲1,那麼release以後,retain count爲0,對象正式被銷燬。若是此時數組中成員的retain count大於1,那麼release以後,retain count大於0,此對象依然沒有被銷燬,內存泄露。若是再方法中不須要再使用這個對象,可是須要將其返回,能夠向這個對象發送autorelease消息將其放入到自動釋放池用以標記這個對象延遲釋放,autorelease並不會影響到對象的引用計數。

ClassA *Func1()
{
  ClassA *obj = [[[ClassA alloc]init]autorelease];
  return obj;
}

當引用程序終止的時候,內存中全部的對象都會被釋放,不管是否放入到自動釋放池中。若是對對象比較大的話不建議放入到自動釋放池中,由於自動釋放池延遲釋放會致使程序佔用內存較多。在iOS程序中會建立許多的自動釋放池,這些自動釋放池都是以棧(先進後出)的形式進行管理的,好比有兩個嵌套的自動釋放池:

@autoreleasepool { 
         
 // 對象的釋放交給 自動釋放池去管理 不用再寫[person release] 
        Person *person = [[[Person alloc] init] autorelease];  
         
        // 再建立一個自動釋放池2 
        @autoreleasepool { 
             
            Person *person2 = [[[Person alloc] init] autorelease]; 
        } 
        
        Person *person3 = [[[Person alloc] init] autorelease];    
    } 

釋放的順序就是person2->person->person3,先釋放內層的,再釋放外層的,同一層的從上到下釋放。

自從ARC出來以後,iOS開發內存管理便方便不少,總結要點以下:

1.__strong:表示引用爲強引用。對應在定義property時的"strong"。全部對象只有當沒有任何一個強引用指向時,纔會被釋放。若是屬性前面不加修飾符,默認的引用方式就是強引用,當須要釋放強引用指向的對象時,須要將強引用置nil。

2.__weak:表示爲弱引用,弱引用不會影響到對象的釋放,就算有一百個弱引用指向某個對象,對象依然會被釋放(當沒有任何一個強引用指向該對象的時候),可是當對象被釋放以後,全部志向該對象的弱引用將會被置爲nil。弱引用能夠防止循環引用,好比delegate就是使用的弱引用。

3.__autoreleasing:表示在autorelease pool中自動釋放對象的引用,和MRC時代autorelease的用法相同。定義property時不能使用這個修飾符,任何一個對象的property都不該該是autorelease型的。如下兩行代碼的意義是相同的。

NSString *str = [[[NSString alloc] initWithFormat:@"hehe"] autorelease]; // MRC
NSString *__autoreleasing str = [[NSString alloc] initWithFormat:@"hehe"]; // ARC

4.聲明IBOutlet時通常應當使用weak,除了對StoryBoard這樣nib中間的頂層對象要用strong


5.weak至關於老版本的assign,strong至關於retain,copy的做用和原來同樣

 

6.不能直接調用dealloc方法,不能調用retain,release,autorelease,retainCount方法,包括@selector(retain)的方式也不行

7.能夠用dealloc方法來管理一些資源,但不能用來釋放實例變量,也不能在dealloc方法裏面去掉[super dealloc]方法,在ARC下父類的dealloc一樣由編譯器來自動完成

相關文章
相關標籤/搜索