概述
適用:Objective-C 2.0中引入了屬性(property),只適用于Mac OS X10.5以上的版本。
修飾符用法
assign修飾符用來修飾值類型和id類型(一般是delegate)的屬性,需要注意的是如果id類型的屬性的修飾符用了assign,當(dāng)你不需要這個屬性時,你必須將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 修飾,就是防止修改某個對象后,對強引用這個對象的屬性造成不必要影響。
引用類型默認(rèn)的修飾符是 strong.
值類型的默認(rèn)修飾符是 assign.
原風(fēng)格
{
float rainHandling;
float snowHandling;
}
- (void)setRainHandling: (float) rainHanding;
- (float) rainHandling;
- (void) setSnowHandling: (float) snowHandling;
- (float) snowHandling;
屬性風(fēng)格
{
float rainHandling;
float snowHandling;
}
@property float ranHanding;
@property float snowHandling;
說明:@prorerty 預(yù)編譯指令的作用是自動聲明屬性的setter和getter方法。屬性的名稱不必與實例變量的名稱相同。,但大多數(shù)情況下它們是一樣的。
.m文件下的修改
@synthesize rainHandling;
@synthesize snowHandling;
@synthesize表示”創(chuàng)建了該屬性的訪問代碼“(在Xcode4.5以后的版本,可以不必使用@synthesize了)
實例變量不是必須的
需要注意頭文件中有兩個叫做rainHandling和snowHandling的實例變量(合成的setter和getter方法會用到這些變量)。如果你沒有聲明這些變量,編譯器也會聲明的。
點表達(dá)式的妙用
[tire setRainHandling:20+i];
[tire setSnowHandling:28+i];
=
tire.rainHandling = 20+i;
tire.snowHandling = 28+i;
[trie rainHandling],[trie snowHandling]
=
trie.rainHandling,trie.snowHandling
如果點表達(dá)式出現(xiàn)在了等號的左邊,該變量名稱的setter方法被調(diào)用;如果點表達(dá)式出現(xiàn)在了等號的右邊,則該變量名稱的getter方法被調(diào)用。
屬性擴展
屬性同樣適用于int、char、BOOL和struct類型。甚至可以定義一個NSRect對象的屬性。
不過對象也會帶來一些麻煩。我們在適用訪問方法對象時需要保留和釋放對象。對于某些對象的值,尤其是字符串的值,你總是會復(fù)制(-copy)它們。而對于其他對象的值,如委托,你根本不會想要保留它們。
為什么要復(fù)制對象?
你想要復(fù)制的字符串參數(shù)。一種常見的錯誤就是從用戶界面(如文本框)中獲得一個字符串,并將其作為某事物的名稱使用。文本框中的字符串通常都是可變字符串,復(fù)制該字符串可以防止因意外的變換而產(chǎn)生不利的影響。
原風(fēng)格
- (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]
}
屬性風(fēng)格
@property (copy) NSString *name;
@property (retain) Engine *engine;//engine屬性使用的只有保留和釋放特性
- 如果copy和retain都沒有使用的話,默認(rèn)為使用assign。
- 如果你不想保留某個變量對象,可以使用assign,這樣可以避免發(fā)生保留死循環(huán)。
- nonatomic 可以在非多線程中使用,可以了提高訪問放的調(diào)用速度
- 系統(tǒng)默認(rèn)為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)默認(rèn)是readwrite,假設(shè)我們不想讓任何人修改它,可以設(shè)置屬性為readonly
- @property (readonly) float shoeSize;
當(dāng)編譯器知道這個@property屬性是只讀的,它將只生成一個getter方法而不會生成setter方法。調(diào)用set方法會報錯,點語法也同樣。
不要變量、getter和setter方法
@dynamic 不生成任何代碼或創(chuàng)建相應(yī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方法,并生成名為默認(rèn)setHidden:的setter方法