Object-c 2.0引入了屬性的概念,使得我們可以通過點方法來通路對象的成員變量。假設有一個類為A, 該類有一個成員對象為mTest,mTest是一個類型為B的對象,現在已經有了一個A類的執行個體對象為a,為了能夠用a.mTest 這樣的方式,我們需要做到以下兩點:
一、在頭檔案中用以下方式将mTest聲明為屬性
聲明屬性的文法:@property 類型 名字
比如我們可以這樣寫:@property(readwrite,nonatomic, retain) B *mTest;
這樣的聲明,最容易讓人迷惑的是類型部分,其實屬性主要分為三類:
1. 讀寫屬性(readwrite/ readonly)
預設為readwrite,表示該屬性既可以讀取,也可以給該屬性變量指派;readonly則表示隻能讀取該屬性變量。
2. 原子屬性 (atomicity/nonatomic)
原子屬性中,atomic是預設值,表示屬性是原子的,支援多線程并發通路(在setter實作中加入了同步鎖),後者是非原子的,适合在非多線程環境中提升效率,沒有加入同步鎖。
3. Setter屬性 (assign/retain/copy)
如果屬性是對象類型,你需要使用retain,assign,copy參數,表示setter方法内部實作的時候,持有對象的方式。其中retain就是增加引用計數,強引用類型。assign就是變量的直接指派,弱引用類型,也是預設值。copy就是把setter的參數複制一遍,再賦給成員變量。 如果你不給出持有對象的方式,編譯器就會給出警告。
屬性的setter類型與記憶體管理密切相關,要相當謹慎使用,很多記憶體錯誤以及程式的莫名其妙崩潰都是由于對屬性的不正确使用造成的。
二、在.m 檔案中用以下方式合成對應的屬性讀取和設定函數
@synthesize mTest;
.m檔案中有了上面這樣一行,編譯器就會自動合成getter函數,如果屬性是可指派的(即屬性類型為readwrite),還會合成setter函數。編譯器合成的getter函數名與屬性名相同,合成的setter函數名則形如setMTest(即将屬性的首字母大寫)。
實際上,我們也可以不用編譯器來幫我們合成方法,自己來實作屬性的存取方法。為了這樣做,我們需要将@synthesize mTest; 這句去掉,同時在.m檔案中實作以下兩個函數:
- (B *) mTest
{
// .......
}
- void setMTest:(B*) b
{
// .............
}
自己去實作存取方法是違背了屬性的初衷的,一般不采用,給大家講這個隻是為了說明問題,僅此而已。