OC語言自學《十一》---- OC(內存管理知識總結)

1、retain、release

  • retain方法給對象的引用計數器+1
  • release方法給對象的引用計數器-1
  • retain方法會返回對象自己,release方法沒有返回值
  • dealloc方法
    • 當一個對象要被回收的時候會被調用
    • 重寫的時候,必定要調用[super dealloc]方法,這句調用必定要放到最後面
  • 空指針
    • OC中沒有空指針異常
    • 沒有指向任何東西的指針(存儲的東西是nil、NULL、0),給空指針發送消息不會報錯
  • 野指針
    • 指向殭屍對象(不可用的內存)的指針,給野指針發送消息會報錯(EXC_BAD_ACCESS)
  • 殭屍對象
    • 所佔用內存已經被回收的對象,殭屍對象不能再使用

2、retain、release使用注意

  • 誰retain,誰release
    • 只要你調用了retain,不管這個對象是如何生成的,你都要調用release
    • 善始善終,有加就有減
  • 曾經讓對象的計數器+1,就必須在最後讓對象計數器-1
  • 若是你經過alloc、new或[mutable]copy來建立一個對象,那麼你必須調用release或autorelease
  • 你想使用某個對象,就應該讓對象的計數器+1(讓對象作一次retain操做)
  • 當你不想在使用某個對象時,咱們就該讓對象的計數器-1(讓對象作一次release操做)
  • 誰retain,誰就release
  • 誰alloc,誰就release

3、set方法和dealloc的內存管理

  • 只要調用alloc,必須有release(autorelease)
  • set方法代碼規範
    • 基本數據類型:直接賦值
    • OC對象類型:

- (void)setCar:(Car *)car
{
   //1.先判斷是否是新傳進來對象
   if(car != _car){
      //2.對舊對象作一次release -1
       [_car release];          
      //3.對新對象作一次retain +1
      _car = [car retain];
   }
}
  • dealloc方法代碼規範
    • 必定要[super dealloc],並且放到最後面
    • 對當前對象(self)所擁有的其餘對象作一次release

- (void)dealloc { /* _speed //直接訪問成員變量 self -> _speed //直接訪問成員變量 self.speed //get方法 [self speed] //get方法 */ NSLog(@"速度爲%d的Car對象被回收了",_speed); [super dealloc]; }

4、@property

  • 經過@property能夠自動生成帶內存管理的setter方法
  • 下面時不帶參數聲明
@property(retain) Book *book;
  • 聲明事後,須要到dealloc方法中去release須要release的成員變量
  • @property的參數
  • set方法內存管理相關的參數
    • retain:release舊址,retain新值(適用於OC對象類型)
    • assign:直接複製,默認的,能夠不寫(適用於非OC對象類型)
    • copy: release舊值,copy新值
  • 是否要生成get方法
    • readonly:只生成getter方法的聲明、實現
    • readwrite:同時生成setter和getter的聲明、實現(默認的)
  • 多線程管理
    • nonatomic :性能高(通常就用這個)
    • atomic    :性能低(默認)
  • setter和getter的名稱(通常用到BOOL類型)
    • getter:設置getter的方法名稱
    • setter:設置setter的方法名稱,必須帶冒號:
  • 返回BOOL類型的方法名通常以is開頭
@property (getter = isRich) BOOL rich;

5、循環引用

  • @class的做用,僅僅告訴編譯器,某個名稱是一個類
  • @class Person;  
  • 開發中引用一個類的規範
    • 在.h文件中用@class來聲明類
    • 在.m文件中用#import來包含類的全部東西
  • @class和#import的區別
    • #import方式會包含被引用類的全部信息,包括被引用類的變量和方法;@class方式只是告訴編譯器在A.h文件中 B *b 只是類的聲明,具體這個類裏有什麼信息,這裏不須要知道,等實現文件中真正要用到時,纔會真正去查看B類中信息
    • 若是有上百個頭文件都#import了同一個文件,或者這些文件依次被#improt,那麼一旦最開始的頭文件稍有改動,後面引用到這個文件的全部類都須要從新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方式就不會出現這種問題了
    • 在.m實現文件中,若是須要引用到被引用類的實體變量或者方法時,還須要使用#import方式引入被引用類
  • 兩端循環引用解決方案
    • 一端@property用retain
    • 一端@property用assign

6、autorelease

  • autorelease的基本用法
    • 會講對象放到一個自動釋放池中
    • 當自動釋放池被銷燬時,會對池子裏面的全部對象作一次release操做
    • 會返回對象自己
    • 調用完autorelease方法後,對象的計數器不變
  • autorelease的好處
    • 不用再關心對象釋放的時間
    • 不用再關心何時調用release方法
  • autorelease的使用注意
    • 佔用內存較大的對象不要隨便使用autorelease
    • 佔用內存較小的對象使用autorelease,沒有太大影響
  • 錯誤寫法:
    • alloc以後調用了autorelease,又調用release

@autoreleasepool {
 //1
 Person *p = [[[Person alloc]init]autorelease];


 //0,野指針錯誤
 //[p release];

}
  • 連續調用屢次autorelease

@autorelease
{
    Person *p = [[[[Person alloc]init]autorelease]autorelease];
}
  • 自動釋放池
    • 在ios程序運行過程當中,會建立無數個池子,這些池子都是以棧結構存在(先進後出)
    • 當一個對象調用autorelease方法時,會將這個對象方到棧頂得釋放池
  • 自動釋放池的建立方式
    • ios 5.0前

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

Person *pp = [[[Person alloc]init]autorelease];
 
[pool release];
  •  ios 5.0開始                    

@autorelease 
{

}
  • autorelease的使用場合
    • 系統自帶的方法裏面沒有包含alloc、new、copy,說明返回的對象都時autorelease的
    • 開發中常常會提供一些類方法,快速建立一個autorelease過的對象
    • 建立對象時,不要直接用類名,通常用self
+ (id)person
{
    return [[[self alloc] init]autorelease];
}
相關文章
相關標籤/搜索