概述
適用:Objective-C 2.0中引入了屬性(property),只適用于Mac OS X10.5以上的版本次员。
修飾符用法
assign修飾符用來修飾值類型和id類型(一般是delegate)的屬性檀训,需要注意的是如果id類型的屬性的修飾符用了assign,當你不需要這個屬性時埂软,你必須將delegate手動置空锈遥,防止野指針產(chǎn)生,這也是為什么 delegate 一般都用 weak 修飾的原因仰美。
weak 和 strong 是 ARC 的產(chǎn)物迷殿,分別表示弱引用類型和強引用類 型。在給 strong 修飾的屬性賦值時咖杂,會將屬性的指針指向新值的地址庆寺,同時持有這個新值(新值的引用計數(shù)被加1)。在給 weak 修飾的屬性賦值時诉字,只是簡單地將屬性的指針指向新值的地址懦尝,不會持有新值。
retain 在 ARC 下基本等同于 strong壤圃。
copy 表示強引用陵霉,但是不會持有新值,而是拷貝一份引用計數(shù)為1的值給屬性伍绳。給這種修飾符修飾的屬性賦值時踊挠,實際上是把 新值調(diào)用 copy 方法后的返回值 賦給屬性。NSString 類型常常用 copy 修飾,就是防止修改某個對象后效床,對強引用這個對象的屬性造成不必要影響睹酌。
引用類型默認的修飾符是 strong.
值類型的默認修飾符是 assign.
原風格
{
float rainHandling;
float snowHandling;
}
- (void)setRainHandling: (float) rainHanding;
- (float) rainHandling;
- (void) setSnowHandling: (float) snowHandling;
- (float) snowHandling;
屬性風格
{
float rainHandling;
float snowHandling;
}
@property float ranHanding;
@property float snowHandling;
說明:@prorerty 預編譯指令的作用是自動聲明屬性的setter和getter方法。屬性的名稱不必與實例變量的名稱相同剩檀。憋沿,但大多數(shù)情況下它們是一樣的。
.m文件下的修改
@synthesize rainHandling;
@synthesize snowHandling;
@synthesize表示”創(chuàng)建了該屬性的訪問代碼“(在Xcode4.5以后的版本沪猴,可以不必使用@synthesize了)
實例變量不是必須的
需要注意頭文件中有兩個叫做rainHandling和snowHandling的實例變量(合成的setter和getter方法會用到這些變量)辐啄。如果你沒有聲明這些變量,編譯器也會聲明的运嗜。
點表達式的妙用
[tire setRainHandling:20+i];
[tire setSnowHandling:28+i];
=
tire.rainHandling = 20+i;
tire.snowHandling = 28+i;
[trie rainHandling],[trie snowHandling]
=
trie.rainHandling,trie.snowHandling
如果點表達式出現(xiàn)在了等號的左邊壶辜,該變量名稱的setter方法被調(diào)用;如果點表達式出現(xiàn)在了等號的右邊洗出,則該變量名稱的getter方法被調(diào)用士复。
屬性擴展
屬性同樣適用于int、char翩活、BOOL和struct類型。甚至可以定義一個NSRect對象的屬性便贵。
不過對象也會帶來一些麻煩菠镇。我們在適用訪問方法對象時需要保留和釋放對象。對于某些對象的值承璃,尤其是字符串的值利耍,你總是會復制(-copy)它們。而對于其他對象的值盔粹,如委托隘梨,你根本不會想要保留它們。
為什么要復制對象舷嗡?
你想要復制的字符串參數(shù)轴猎。一種常見的錯誤就是從用戶界面(如文本框)中獲得一個字符串,并將其作為某事物的名稱使用进萄。文本框中的字符串通常都是可變字符串捻脖,復制該字符串可以防止因意外的變換而產(chǎn)生不利的影響。
原風格
- (id)init
{
name = [[NSString alloc] initWithString:@"Car"];
}
- (void)setName:(NSString *)newName
{
[name release];
name = [newName copy];
} //setName
- (NSString *)name
{
return (name);
}//name
- (void)dealloc
{
[name release]
}
屬性風格
@property (copy) NSString *name;
@property (retain) Engine *engine;//engine屬性使用的只有保留和釋放特性
- 如果copy和retain都沒有使用的話中鼠,默認為使用assign可婶。
- 如果你不想保留某個變量對象,可以使用assign援雇,這樣可以避免發(fā)生保留死循環(huán)矛渴。
- nonatomic 可以在非多線程中使用,可以了提高訪問放的調(diào)用速度
- 系統(tǒng)默認為nonatomic和assign惫搏。你可以為可保留的指針(Objective-C對象)指定retain和copy特性具温。而其他C類型和不可保留的指定必須使用assign特性并且要手動來管理內(nèi)存蚕涤。
- 如果自己定義setter或getter方法,那么就不能使用atomic特性了桂躏,必須使用nonatomic特性钻趋。
名稱的使用
.h中
{
NSString *appellation;
Engine *engine;
}
@property (copy) NSString *name;
@property (retain) Engine *engine;
.m中
@synthesize name = appellation;
編譯器扔將創(chuàng)建-setName:和-name方法,但在實現(xiàn)代碼中用的卻是appellation實例變量剂习。
只讀屬性
系統(tǒng)默認是readwrite蛮位,假設(shè)我們不想讓任何人修改它,可以設(shè)置屬性為readonly
- @property (readonly) float shoeSize;
當編譯器知道這個@property屬性是只讀的鳞绕,它將只生成一個getter方法而不會生成setter方法失仁。調(diào)用set方法會報錯,點語法也同樣们何。
不要變量萄焦、getter和setter方法
@dynamic 不生成任何代碼或創(chuàng)建相應的實例變量。
創(chuàng)建一個能在運行時計算此值的訪問方法冤竹,不能set這個值拂封。
@property (readonly) float bodyMassIndex;
- (float)bodyMassIndex;
- (float)bodyMassIndex
{
//compute and return bodyMassIndex
}
換個名字(getter= | setter=)
@property (getter=isHidden) BOOL hidden;
它告訴編譯器生成名為isHidden的getter方法,并生成名為默認setHidden:的setter方法