移動裝置的記憶體極其有限(iphone 4記憶體512m),每個app所能占用的記憶體是有限制的(幾十兆而已)。
當app所占用的記憶體較多時,系統會發出記憶體警告,這時得回收一些不需要再使用的記憶體空間。比如回收一些不需要使用的對象、變量等
管理範圍:任何繼承了nsobject的對象,對其他基本資料類型(int、char、float、double、struct、enum等)無效,和 java 不一樣,oc 開始的時候沒有垃圾自動回收機制。

每個oc對象都有自己的引用計數器,是一個四位元組的整數,表示“對象被引用的次數”,即有多少人正在使用這個oc對象
每個oc對象内部專門有4個位元組的存儲空間來存儲引用計數器(面試題)
引用計數器的作用
當使用alloc、new或者copy建立一個新對象時,新對象的引用計數器預設就是1,當一個對象的引用計數器值為0時,對象占用的記憶體就會被系統回收。換句話說,如果對象的計數器不為0,那麼在整個程式運作過程,它占用的記憶體就不可能被回收,除非整個程式已經退出。
引用計數器的操作
給對象發送一條retain消息(代表調用這個對象方法),可以使引用計數器值+1(retain方法傳回對象本身)
給對象發送一條release消息,可以使引用計數器值-1,沒有傳回值
可以給對象發送retaincount消息獲得目前的引用計數器值
對象的銷毀(ios6之前)
當一個對象的引用計數器值為0時,那麼它将被銷毀,其占用的記憶體被系統回收,
當一個對象被銷毀時,系統會自動向對象發送一條dealloc消息,
一般會重寫dealloc方法,在這裡釋放相關資源,dealloc就像對象的臨終遺言,
一旦重寫了dealloc方法,就必須調用[super dealloc],并且放在最後面調用(類似 c++的析構函數,析構函數的調用順序和構造函數的調用順序完全相反),
不要直接調用dealloc方法,
一旦對象被回收了,它占用的記憶體就不再可用,堅持使用會導緻程式崩潰(野指針錯誤)
xcode的設定,取消 arc
要想手動調用retain、release等方法,在建立項目的時候不要勾選arc(自動引用計數)
1.當需要使用int類型的變量的時候,可以像寫c的程式一樣,用int,也可以用nsinteger,但更推薦使用nsinteger,因為這樣就不用考慮裝置是32位的還是64位的。
2.nsuinteger是無符号的,即沒有負數,nsinteger是有符号的。
開啟僵屍對象監控
預設情況下,xcode是不會管僵屍對象的,使用一塊被釋放的記憶體也不會報錯。為了友善調試,應該開啟僵屍對象監控
記憶體管理原則
qq堂開房間原理:隻要房間還有人在用,就不會解散
隻要還有人在用某個對象,那麼這個對象就不會被回收
隻要你想用這個對象,就讓對象的計數器+1
當你不再使用這個對象時,就讓對象的計數器-1
誰建立,誰release
如果你通過alloc、new或[mutable]copy來建立一個對象,那麼你必須調用release或autorelease,換句話說,不是你建立的,就不用你去[auto]release
誰retain,誰release
隻要你調用了retain,無論這個對象是如何生成的,你都要調用release
總結
有始有終,有加就有減
曾經讓對象的計數器+1,就必須在最後讓對象計數器-1
你想使用(占用)某個對象,就應該讓對象的計數器+1(讓對象做一次retain操作),不想再使用(占用)某個對象,就應該讓對象的計數器-1(讓對象做一次release)
set方法的記憶體管理
如果有個oc對象類型的成員變量,就必須管理這個成員變量的記憶體。比如有個book *_book,而我們之前的做法并不嚴謹。
記憶體管理代碼規範:
1.隻要調用了alloc,必須有release(autorelease), 對象不是通過alloc産生的,就不需要release
2.set方法的代碼規範
1> 基本資料類型:直接複制
2> oc對象類型
3.dealloc方法的代碼規範
1> 一定要[super dealloc],而且放到最後面
2> 對self(目前)所擁有的其他對象做一次release
什麼是碼農,這樣的重複代碼的編寫就是碼農的工作,so蘋果出了對策,ide 自動完成一些重複性代碼的編寫工作。
xcode 可以幫我們省掉編寫那些惡心代碼的工作。使用@property自動生成記憶體管理的代碼,但是 dealloc 方法還是要自己寫,這時候就有了 arc,ios5之後出的新特性。
@property參數
控制set方法的記憶體管理
retain : release舊值,retain新值(用于oc對象)
assign : 直接指派,不做任何記憶體管理(預設,用于非oc對象類型)
copy : release舊值,copy新值(一般用于nsstring *)
readwrite 同時生成set方法和get方法(預設),這裡把 set 看成寫,get 看成讀取,就很好了解了。
readonly 隻會生成get方法(隻讀,就是隻是擷取,那麼就是 get)
atomic 性能低(預設)
nonatomic 性能高(寫程式要使用這個)
setter : 設定set方法的名稱,一定有個冒号:
getter : 設定get方法的名稱
使用場景;對于循環依賴關系來說,比方a類引用b類,同時b類也引用a類
這種代碼直接編譯會報錯。當使用@class在兩個類互相聲明,就不會出現編譯報錯
用法概括
使用 @class 類名; 就可以引用一個類,說明一下它是一個類
和#import的差別
#import方式會包含被引用類的所有資訊,包括被引用類的變量和方法;
@class方式隻是告訴編譯器在a.h檔案中 b *b 隻是類的聲明,具體這個類裡有什麼資訊,這裡不需要知道,等實作檔案中真正要用到時,才會真正去檢視b類中資訊,如果有上百個頭檔案都#import了同一個檔案,或者這些檔案依次被#improt,那麼一旦最開始的頭檔案稍有改動,後面引用到這個檔案的所有類都需要重新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方式就不會出現這種問題了。
在.m實作檔案中,如果需要引用到被引用類的實體變量或者方法時,還需要使用#import方式引入被引用類
循環retain
比如a對象retain了b對象,b對象retain了a對象,這樣會導緻a對象和b對象永遠無法釋放
解決方案
當兩端互相引用時,應該一端用retain、一端用assign
@class的作用:僅僅告訴編譯器,某個名稱是一個類
@class person; 僅僅告訴編譯器,person是一個類,不會把類的方法等引入
實際開發中引用一個類的規範是:
1> 在.h檔案中用@class來聲明類,比如,有100個類同時引用了 card 類,如果 card 修改了,那麼剩下的100個類也要重新引入編譯,效率不高,且還能解決雙端引用(循環引用)的出現錯誤問題。
2> 在.m檔案中用#import來包含類的所有東西
為了提高編譯的效率!頭檔案不使用#import,隻有一個特例,那就是在繼承裡,父類需要使用#import 引入到子類
兩端循環引用解決方案,這是特例,差別對待,以前說了,對象用 retain,非對象不需要記憶體管理,使用 assign 就行了,但是這裡特殊
1> 一端用retain
2> 一端用assign
autorelease方法(半自動釋放)
autorelease
給某個對象發送一條autorelease消息時,就會将這個對象加到一個自動釋放池中
當自動釋放池銷毀時,會給池子裡面的所有對象發送一條release消息
調用autorelease方法時并不會改變對象的計數器
autorelease 方法傳回對象本身
autorelease實際上隻是把對release的調用延遲了,對于每一次autorelease,系統隻是把該對象放入了目前的@autoreleasepool中,當該pool被釋放時,該pool中的所有對象會被調用release
使用 autorelease 方法防止了每次使用對象,都要在對象 release 之前使用的弊端,因為那樣總是小心翼翼的,怕出現野指針。但是出現了 arc 之後這些都不需要了。
ios 5.0後,以後一直使用這個了.
ios 5.0前
在程式運作過程中,可以建立多個自動釋放池,它們是以棧的形式存在記憶體中,oc對象隻需要發送一條autorelease消息,就會把這個對象添加到最近的自動釋放池中(棧頂的釋放池)
跟release的對比
以前:
book *book = [[book alloc] init];
[book release];
現在:
book *book = [[[book alloc] init] autorelease];
// 不要再調用[book release];但是這樣顯得代碼很長,臃腫,能不能建立對象的時候,直接就是放入自動釋放池裡呢?可以的:
一般可以為類添加一個快速建立對象的類方法
外界調用[book book]時,根本不用考慮在什麼時候釋放傳回的book對象,實際開發中常用。
開發中經常會提供一些類方法,快速建立一個已經autorelease過的對象,建立對象時不要直接用類名,用self,因為這樣寫,此類的子類都能調用這個方法,自動識别,self 指向調用這個方法的類,不會出錯。
一般來說,除了alloc、new或copy之外,其他的方法建立的對象都被聲明了autorelease
比如下面的對象都已經是autorelease的,不需要再release
一、計數器的基本操作
1> retain : +1
2> release :-1
3> retaincount : 獲得計數器
二、set方法的記憶體管理
1> set方法的實作
2> dealloc方法的實作(不要直接調用dealloc)
三、@property參數
1> oc對象類型
@property (nonatomic, retain) 類名 *屬性名;
@property (nonatomic, retain) car *car;
@property (nonatomic, retain) id car;
// 被retain過的屬性,必須在dealloc方法中release屬性
- (void)dealloc
{
[_car release];
[super dealloc];
}
2> 非oc對象類型(int\float\enum\struct)
@property (nonatomic, assign) 類型名稱 屬性名;
@property (nonatomic, assign) int age;
四、autorelease
1.系統自帶的方法中,如果不包含alloc、new、copy,那麼這些方法傳回的對象都是已經autorelease過的
[nsstring stringwithformat:....];
[nsdate date];
2.開發中經常寫一些類方法快速建立一個autorelease的對象
* 建立對象的時候不要直接使用類名,用self
辛苦的勞動,轉載請注明出處,謝謝……
http://www.cnblogs.com/kubixuesheng/p/4314322.html