iOS內(nèi)存管理方式

內(nèi)存管理方式
  • 垃圾回收機制 (Garbage - collection)
    程序員只需要開辟內(nèi)存空間,不需要用代碼的形式釋放,系統(tǒng)來判斷哪些空間不再被使用,并回收這些內(nèi)存空間,以便再次分配。整個回收的過程不需要寫任何代碼,由系統(tǒng)自動完成垃圾回收。Java開發(fā)中一直使用的就是垃圾回收技術(shù)。
  • MRC (Manual Reference Counting)
    人工引用計數(shù):內(nèi)存的開辟和釋放都由程序代碼進行控制。相對垃圾回收來說,對內(nèi)存的控制更加靈活,可以在需要釋放的時候及時釋放,對程序員的要求較高,程序員要熟悉內(nèi)存管理的機制。

  • ARC (Auto Reference Counting)
    自動引用計數(shù):iOS 5.0的編譯器特性,它允許用戶只開辟空間,不用去釋放空間。它不是垃圾回收!它的本質(zhì)還是MRC,只是編譯器幫程序員默認加了釋放的代碼。

iOS支持兩種內(nèi)存管理方式:ARC 和 MRC

ARC 是基于MRC 的, MRC的內(nèi)存管理機制是: 引用計數(shù)

  • C語言中,使用malloc和free 進行堆內(nèi)存的創(chuàng)建和釋放。堆內(nèi)存只有正在使用和銷毀兩種狀態(tài)
  • 實際開發(fā)中,可能會遇到兩個以上的指針使用同一塊內(nèi)存。C語言無法記錄內(nèi)存使用者的個數(shù)。
圖1-1
圖1-2
引用計數(shù)
  • OC采用引用計數(shù)機制,每個對象都有一個引用計數(shù)器,用來記錄當(dāng)前對象的引用次數(shù)。當(dāng)一個新的引用指向?qū)ο髸r,引用計數(shù)器就+1,去掉一個引用時,引用計數(shù)就-1。當(dāng)引用計數(shù)到0時,該對象的空間就被被系統(tǒng)回收。
OC對象的操作 OC中對應(yīng)的方法
生成對象 alloc
持有對象 retain
釋放對象 release / autorelease
銷毀對象 dealloc
  • alloc 開辟內(nèi)存空間,讓被開辟的內(nèi)存空間的引用計數(shù)從0變?yōu)?
  • retain 引用計數(shù)+1,如果對象之前引用計數(shù)為1,retain之后變?yōu)?
  • copy 把某一對象的內(nèi)容拷貝一份,拷貝出新的對象,原有對象的引用計數(shù)不變,新的對象的引用計數(shù)變1
  • release 引用計數(shù)立即-1,如果對象之前的引用計數(shù)為4,release之后變?yōu)?,如果之前引用計數(shù)為1,release之后變?yōu)?,內(nèi)存被系統(tǒng)回收
  • autorelease 未來的某一時刻引用計數(shù)-1,如果對象之前的引用計數(shù)為4,autorelease之后仍然為4,未來某個時刻會變?yōu)?。通過autoreleasepool自動釋放池,控制autorelease對象的釋放。
屬性的內(nèi)存管理
  • 在MRC模式下,同時重寫setter和getter方法來說明各個屬性(@property)修飾符,是如何對內(nèi)存進行管理的。
    注意事項:
    1.在同時重寫setter和getter方法的時候,系統(tǒng)不會為該屬性生成員變量需
    要加 @synthesize propertyName = _propertyName
    如下寫法會造成死循環(huán)
    2.在set方法中,self.age=age;相當(dāng)于是[self setAge:age];
    3.在get方法中,return self.age;相當(dāng)于是[self age];
    1.assign
    簡單的賦值,不更改引用計數(shù)一般修飾基本數(shù)據(jù)類型(char, short, int, float, double)

      @synthesize num = _num;
      @property(nonatomic, assign)NSInteger num;
      // getter
      - (NSInteger)num
      {
          return _num;
      }  
    
      // setter
      -(void)setNum:(NSInteger)num
      {
          _num = num;
      }
    

    2.retain
    釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數(shù)為1

      @synthesize name = _name;
      @property(nonatomic, retain)NSString *name;
      //  getter
      - (NSString *)name
      {
          return [[_name retain] autorelease];
      }
    
      // setter
      - (void)setName:(NSString *)name
      {
          // 判斷傳進來的字符串和本身屬性的字符串是否相同,不同才賦值
          if (name != _name) {
      
              [_name release]; // 先將原字符串的引用計數(shù) -1,防止內(nèi)存泄露
      
              _name = [name retain]; // 對新字符串的引用計數(shù) +1 ,防止其他指針釋放該空間
      
          }
    
      }
    

    3.copy

      @synthesize gender = _gender;
      @property(nonatomic, copy)NSString *gender;
    
      // getter
      - (NSString *)gender
      {
          return [[_gender retain] autorelease];
      }
    
      // setter
      - (void)setGender:(NSString *)gender
      {
          if (gender != _gender) {
      
              [_gender release]; // 斷掉之前的聯(lián)系
      
              _gender = [gender mutableCopy]; 
              // 注:mutableCopy 為深拷貝
              //對原對象復(fù)制一份放到新的空間,原對象引用計數(shù)沒改變,新對象引用計數(shù)為 +1
          }
      }
    
    • 偽拷貝:(只拷貝地址,沒拷貝內(nèi)容)
    • 淺拷貝:(會產(chǎn)生新的對象,但是它與原來的對象共用實例變量)
    • 深拷貝:(會產(chǎn)生新的對象,并且會把原對象的內(nèi)容完全復(fù)制一份,不會再受原對象影響)

    4.strong
    strong等同retain
    在MRC模式下使用retain, ARC模式下使用strong
    5.weak
    weak比assign多了一個功能,當(dāng)對象消失后自動把指針變成nil

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容