範圍:
任何繼承了nsobject的物件,對基本資料型別無效
原理:每個物件內部都儲存了乙個與之相關聯的整數,稱為引用計數器
當使用alloc、new或者copy建立乙個物件時,物件的引用計數器被設定為1
給物件傳送一條retain訊息,可以使引用計數器值+1
給物件傳送一條release訊息,可以使引用計數器值-1
當乙個物件的引用計數器值為0時,那麼它將被銷毀,其占用的記憶體被系統**,oc也會自動向物件傳送一條dealloc訊息。一般會重寫dealloc方法,在這裡釋放相關資源。一定不要直接呼叫dealloc方法
可以給物件傳送retaincount訊息獲得當前的引用計數器值
1.誰建立,誰釋放(「誰汙染,誰治理」)。如果你通過alloc、new或(mutable)copy來建立乙個物件,那麼你必須呼叫release或autorelease。換句話說,不是你建立的,就不用你去釋放
2.一般來說,除了alloc、new或copy之外的方法建立的物件都被宣告了autorelease
3.誰retain,誰release。只要你呼叫了retain,無論這個物件是如何生成的,你都要呼叫release
#import
#import "book.h"
@inte***ce student
@property book *book;
@end
#import "student.h"
@implementation student
@synthesize book = _book;
- (void)setbook:(book *)book
}- (void)dealloc
@end
通常引用乙個類有兩種辦法:
一種是通過#import方式引入;
一種是通過@class引入
兩種方式的區別:
1、#import方式會包含被引用類的所有資訊,包括被引用類的變數和方法;@class方式只是告訴編譯器在a.h檔案中 b *b 只是類的宣告,具體這個類裡有什麼資訊,這裡不需要知道,等實現檔案中真正要用到時,才會真正去檢視b類中資訊
2、使用@class方式由於只需要知道被引用類(b類)的名稱就可以了,而在實現類由於要用到被引用類中的實體變數和方法,所以在.m檔案中需要使用#import來包含被引用類的標頭檔案
3、如果有上百個頭檔案都#import了同乙個檔案,或者這些檔案依次被#improt,那麼一旦最開始的標頭檔案稍有改動,後面引用到這個檔案的所有類都需要重新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方式就不會出現這種問題了
#import
@class book;
@inte***ce student
@property (retain) book *book;
@end
#import "student.h"
#import "book.h"
@implementation student
//@synthesize會自動展開setter和getter, 隱藏了記憶體管理細節
@synthesize book = _book;
- (void)dealloc
@end
自動釋放池是oc裡面的一種記憶體自動**機制,一般可以將一些臨時變數新增到自動釋放池中,統一**釋放
當自動釋放池銷毀時,池裡面的所有物件都會呼叫一次release方法
oc物件只需要傳送一條autorelease訊息,就會把這個物件新增到最近的自動釋放池中(棧頂的釋放池)
autorelease實際上只是把對release的呼叫延遲了,對於每一次autorelease,系統只是把該物件放入了當前的autorelease pool中,當該pool被釋放時,該pool中的所有物件會被呼叫release
ios 5.0後
@autoreleasepool
ios 5.0前
nsautoreleasepool *pool = [[nsautoreleasepool alloc] init];
// .....
[pool release]; // 或[pool drain];
以前:book *book = [[book alloc] init];
[student setbook:book];
[book release];
現在:book *book = [[[book alloc] init] autorelease];
[student setbook:book];
// 不要再呼叫[book release];
一般可以為類新增乙個快速建立物件的靜態方法
+(id)book
外界呼叫[book book]時,根本不用考慮在什麼時候釋放返回的book物件
在iphone專案中,main()中有乙個預設的autorelease pool,程式開始時建立,程式退出時銷毀,按照對autorelease的理解,豈不是autorelease pool裡的所有物件在程式退出時才release,這樣跟記憶體洩露有什麼區別?
對於每乙個runloop, 系統會隱式建立乙個autorelease pool,並且把建立好的pool放在棧頂,所有的pool會構成乙個棧式結構。在每乙個runloop結束時,當前棧頂的pool會被銷毀,這樣這個pool裡的每個物件會執行release操作
在arc下,不能使用[[nsautoreleasepool alloc] init],而應當使用@autoreleasepool
不要把大量迴圈操作放到同乙個nsautoreleasepool之間,這樣會造成記憶體峰值的上公升
盡量避免對大記憶體使用該方法,對於這種延遲釋放機制,還是盡量少用
sdk中一般利用靜態方法建立並返回的物件都是已經autorelease的,不需要再進行release操作
如[nsnumber numberwithint:10];返回的物件是不需要再release的。
但是通過[[nsnumber alloc] initwithint:10]建立的物件需要release
格式:@property(引數1,引數2)型別 名字;
引數可有可無, 比如:
@property int age;
@property(nonatomic,retain) uibutton* btn;
引數主要分為3類
讀寫屬性:readwrite/readonly
setter處理:assign/retain/copy
原子性:atomic/nonatomic
@property屬性預設為atomic,提供多執行緒安全
在多執行緒環境下,原子操作是必要的,否則有可能引起錯誤的結果
加了atomic,setter/getter是乙個原子操作。如果有多個執行緒同時呼叫setter的話,不會出現某乙個執行緒執行setter全部語句之前,另乙個執行緒開始執行setter的情況,相當於函式頭尾加了鎖一樣
禁止多執行緒,變數保護,提高效能
atomic是oc使用的一種執行緒保護技術,防止在寫入未完成的時候被另外乙個執行緒讀取,造成資料錯誤。而這種機制是耗費系統資源的,所以在iphone這種小型裝置上,如果沒有使用多執行緒間的通訊程式設計,那麼nonatomic是乙個非常好的選擇
如果不需要多執行緒支援的話,用nonatomic就夠了,另外由於不涉及鎖操作,所以它執行相對快點
readwrite: 產生setter\getter
readonly: 只產生簡單的getter,沒有setter。
assign: 預設型別,setter方法直接賦值,而不進行retain操作
retain: setter方法release舊值,再retain新值
copy: setter方法release舊值,再copy新值
分析下面一種情景:(假設都是retain引用)
物件a引用了物件b,物件b引用了物件c,物件c引用了物件b.
這時候b和c的引用計數分別是2和1.當a不再使用b,呼叫release釋放對b的所有權,因為c還引用了b,所以b的引用計數為1,b不會被釋放。b不釋放,c的引用計數就是1,c也不會被釋放。從此,b和c永遠留在記憶體中
為了打斷上面這種迴圈引用,b和c互相引用時,應該一端使用ratain,另一端使用assign
arc,就是由編譯器**中自動加入了
retain/release
。要注意的是,
arc並不是
gc,它只是一種**靜態分析工具 從
ios 5/mac os x 10.7
開始匯入,利用
xcode4.2
可以使用該機制
優點:不需要擔心煩人的記憶體管理和記憶體洩露
**的總量變少了
**效率高,由於使用編譯器管理引用計數,減少了低效**的可能性
缺點:要記住新的
arc規則、關鍵字、特性
使用一些舊**、第三方**的時候比較麻煩,可能要修改編譯開關,
xcode4.2
中預設arc
是yes
的狀態retain, release, autorelease, dealloc由編譯器自動插入,不能在**中呼叫
dealloc雖然可以被過載,但是不能呼叫[super dealloc]
不能使用nsautoreleasepool,應該使用@autoreleasepool塊
不能使用」new」開頭的屬性名稱
ios記憶體管理
引用計數 每個物件有乙個與之相關的整數,稱作 引用計數器 或者 保留計數器 當某段 需要訪問乙個物件時,該段 會將物件的保留計數器 1,表示需要訪問這個物件 當結束對該物件的訪問時,保留計數器 1,表示它不在訪問該物件 當保留計數器為0時,物件被銷毀,所佔記憶體被系統收回。當使用new retain...
iOS記憶體管理
前提 1 以下是針對cocoa物件,不包括core foundation 2 cocoa物件都是用引用計數來跟蹤物件的記憶體使用情況的。3 在子類裡面父類先初始化和後釋放的原則。自己想下為什麼 棧空間和堆空間的區別。我們說的記憶體管理都是基於堆空間的,因為函式內的棧空間是由編譯器自己控制的。關於co...
IOS 記憶體管理
ios記憶體管理一直是頭疼的問題,有時間做些簡單的筆記 使用assign 對基礎資料型別 nsinteger cgfloat 和c 資料型別 int,float,double,char,等等 使用copy 對 nsstring 使用 retain 對其他 nsobject 和其子類 lnonatom...