Objective-C 2.0 with Cocoa Foundation--- 9,內存管理


9.1前言

   內存管理在objective-C 2.0中是非常重要的,內存管理做得好不好,最直觀的就是反應在你的程序crash上面。想要你的程序健壯穩定,那么請務必搞明白內存管理。

9.2 objective-C 2.0是怎樣一個內存機制?

   在objective-C 2.0語言中,內存管理主要是基於一個 release count的值來進行判斷系統是否要回收該內存。當某對象的 retain count等於0時,系統則會回收這段內存。所以當我們想要釋放掉某項目時,我們只需要使其retain count等於0即可。當我們想要hold住該段內存以便后面繼續使用(具體怎么用將會在后面提到)那么你只需要保證在你要使用它之前 它的retain count>0即可。為何蘋果要這樣做?等下告訴你。

   首先還是說明 retain count是如何去操作的。假設我們有一個class A:NSObject,然后我們聲明一個變量  A *a,不用在意它是臨時變量還是類屬性變量,這時候它的retain count等於0;當我們給這個變量創建內存空間的時候 我們會使用NSObject類的 alloc 函數:a=[A alloc];這時候 a的retain count則會+1,能使 retain count +1的函數不止有alloc,還有 [a retain],和[a copy],關於這兩個函數會在什么時候使用以及他們的區別,將在后面討論。要想使retain count -1 你需要調用函數 [a release];那么寫一串代碼來直觀的表示retain count的變化:

 

#import  " A.h "

/* * 略* */

-( void) retainCountDemo
{
   A *a;                    // retain count of a is 0
  a = [A alloc];           // retain count of a is 1
  [a retain];               // retain count of a is 2
  [a release];              // retain count of a is 1
  A* a1 = [a copy];       // retain count of a1 is 1,and a's is 1 too
  [a release];             // retain count of a is 0, and it will be dealloced
  [a1 release];            // retain count of a1 is 0, and it will be dealloced
  return;
}

 

9.3 copy 和 retain的區別?

     copy和retain的區別在於它們的字面意思,不同之處在於一個是直接引用(比如說對象的引用),然后retain count+1,另外一個是復制使用(比如說字符串的使用),將復制到的對象a1的retain count+1.

9.4 他們有什么用?

     objective-C 2.0是一門面向對象的語言,通過使用 retain count來就可以讓開發者在各自的模塊中創建使用以后就“釋放”,而不用擔心影響到其他模塊如果同時會使用到該變量而造成的crash。最典型也是最常用的就是我們的NSURLConnection類里面的request,這種異步請求,你並不知道什么時候該釋放,因為你沒法判斷什么時候請求能夠返回,所以通過使用retain count 你只關心你創建了一個 NSURLConnction,在設置完接收對象,發送完請求以后你就可以release掉它了,而無需關心內存泄露之類的問題。因為在發送請求的時候,NSURLConnction會將自己retain一次,這時候的retain count變為2,你在自己的函數中調用release的時候retaincount則變為1,而當該請求返回的時候,完成回調函數,會自動調用release一次,這時候NSURLConnction的retain count變為0而釋放掉。

    通過上面的例子來總結,我們可以發現,其實這是一種延遲釋放的機制(好吧,這個詞是我自己想到的)。依照這個我們可以解決很多對象共用而不知道該誰去管理內存的問題,蘋果的做法就是:管好你自己,你自己alloc+retain多少次,那么請你release多少次。所以,內存管理最基本的就是管好你自己!

 

9.5 內存管理有沒有更簡單點的方法呢?

     有!但是不建議使用。

    方法1:autorelease函數,通過函數名你應該可以知道這個是幫你自動release的。但是需要注意的是這個函數只會自動幫你release1次,你如果在中間使用了retain之類的,所以還請手動release。同時這個有一個致命的缺點,你想用autorelease在class A中創建對象然后傳遞給class B使用的話這是非常危險的,autorelease是基於系統自帶的自動釋放池來進行內存管理,系統會每隔一段時間去檢測施放池中的對象,並且釋放不在使用的對象。當你傳遞給B的時候,還沒來得及使用,被自動釋放掉了,那么你的程序又會crash。所以 autorelease通常都是在局部對象中使用。

    方法2:IOS 5 ARC(Automatic Reference Counting),蘋果終於發現了做IOS開發有太多無證程序猿了,經常因為內存釋放不好而導致野指針,內存泄露,各種問題的存在。所以蘋果在IOS5的SDK中加了這么一個東西,自動引用計數器。好了,這下各位可以放心的使用,而不用麻煩的去數retain release了。如果你能保證你的客戶都會乖乖升級到IOS5的話…… 顯然,暫時這東西還不太靠譜……

 

9.6 稍微高級點的應用:

     於是我就只想到一個大量生成的臨時對象和自動釋放池這兩個名詞,具體如何使用,請去查閱蘋果API,keywords:NSAutoreleasePool。

  

9.7 后記:

     上面所寫都是我自己對Objective-C的理解和自己以前所犯錯誤而總結出來的經驗,遺憾的是正好我高考語文考試不及格,所以寫的文章也不太好懂,還請見諒,如果有什么疑問或者意見,還請指出一起討論學習。實例代碼,非常簡單,如果有朋友看了也不太明白,還請自己寫demo驗證。對於委托(delegate),通知(notification),屬性等這些東西本來是想也在這里說一說的,但是因為思維跳躍比較大,所以還是抽時間另外寫出來。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM