【iOS開發】內存管理之基礎介紹 – iPhone手機開發 iPhone軟體開發教學課程

前言

【iOS開發】內存管理之基礎介紹,內存管理是程序設計中很重要的一部分,程序在運行的過程中消耗內存,運行結束後釋放占用的內存。如果程序運行時一直分配內存而不及時釋放無用的內存,會造成這樣的後果:程序占用的內存越來越大,直至內存消耗殫盡,程序因無內存可用導致崩潰,這樣的情況我們稱之為內存泄漏。

一、 引用計數

在OC中,對象什麼時候會被釋放(或者對象占用的內存什麼時候會被回收利用)?

答案:當對象沒有被任何變量引用的時候,就會被釋放。

那怎麼知道對象已經沒有被引用瞭呢?

OC采用引用計數(reference counting)的技術來進行管理:
1)每個對象都有一個關聯的整數,稱為引用計數器
2)當代碼需要使用該對象時,則將對象的引用計數加1
3)當代碼結束使用該對象時,則將對象的引用計數減1
4)當引用計數的值變為0時,表示對象沒有被任何代碼使用,此時對象將被釋放。

與之對應的消息發送方法如下:

1)當對象被創建(通過alloc、new或copy等方法)時,其引用計數初始值為1
2)給對象發送retain消息,其引用計數加1
3)給對象發送release消息,其引用計數減1
4)當對象引用計數歸0時,ObjC給對象發送dealloc消息銷毀對象

二、 iOS的內存管理規則

內存管理基本原則,總的來講有三點:

1)當你通過new、alloc或copy方法創建一個對象時,它的引用計數為1,當不再使用該對象時,應該向對象發送release或者autorelease消息釋放對象。
2)當你通過其他方法獲得一個對象時,如果對象引用計數為1且被設置為autorelease,則不需要執行任何釋放對象的操作;
3)如果你打算取得對象所有權,就需要保留對象並在操作完成之後釋放,且必須保證retain和release的次數對等。

三、 經典內存泄漏及其解決方案

3.1 循環引用

3.2 循環中臨時對象占用內存大

例子01:需要循環創建100000個學生對象來學習
 for (int i = 0; i < 10000; i ++) 
  {
         Student * s = [[Student alloc]init];
         [s study];
    }

  該循環內產生大量的臨時對象,直至循環結束才釋放,可能導致內存泄漏,解決方法和上文中提到的自動釋放池常見問題類似:在循環中創建自己的autoReleasePool,及時釋放占用內存大的臨時變量,減少內存占用峰值。
  

for (int i = 0; i < 10000; i ++) 
{
         @autoreleasepool {
             Student * s = [[Student alloc]init];
             [s study];
         }
}

然而有時候autoReleasePool也不是萬能的。

例子02:假如有2000張圖片,每張1M左右,現在需要獲取所有圖片的尺寸,你會怎麼做?

如果這樣做

     for (int i = 0; i < 5000; i ++) 
     {
         CGSize size = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg",i]].size;

     }

用imageNamed方法加載圖片占用Cache的內存,autoReleasePool也不能釋放,對此問題需要另外的解決方法。就是采用讀文件和autoReleasePool結合的方式。

     for (int i = 0; i < 5000; i ++) 
     {
         @autoreleasepool {
             CGSize size = [UIImage imageWithContentsOfFile:filePath].size;

          }
     }

發佈留言