1.@property 屬性
在我們聲明property這個(gè)關(guān)鍵字的時(shí)候例如:
@property (nonatomic, strong) NSMutableArray *dataArray;
這個(gè)時(shí)候默認(rèn)編譯器會(huì)幫我們聲明一個(gè)Ivar(帶下劃線(xiàn)的成員變量_dataArray),還有對(duì)應(yīng)的setter和getter方法,使用了property之后,就可以使用iOS中的點(diǎn)語(yǔ)法,可以通過(guò)self.dataArray來(lái)使用這個(gè)實(shí)例變量,實(shí)質(zhì)上也是調(diào)用了對(duì)應(yīng)的setter和getter方法。
@property的特性,@property還有一些關(guān)鍵字,它們都是有特殊作用的,比如上述代碼中的nonatomic,strong.我把它們分為三類(lèi),分別是:原子性,存取器控制,內(nèi)存管理。
原子性:
atomic(默認(rèn)):atomic意為操作是原子的,意味著只有一個(gè)線(xiàn)程訪(fǎng)問(wèn)實(shí)例變量。atomic是線(xiàn)程安全的,至少在當(dāng)前的存取器上是安全的。但是并不意味著它是線(xiàn)程安全的,它會(huì)增加正確的幾率,能夠更好的避免線(xiàn)程的錯(cuò)誤,但是它仍然是線(xiàn)程不安全的。它是一個(gè)默認(rèn)的特性,但是很少使用,因?yàn)楸容^影響效率,這跟ARM平臺(tái)和內(nèi)部鎖機(jī)制有關(guān)。
nonatomic:nonatomic跟atomic剛好相反。表示非原子的,可以被多個(gè)線(xiàn)程訪(fǎng)問(wèn)。它的效率比atomic快。但不能保證在多線(xiàn)程環(huán)境下的安全性,在單線(xiàn)程和明確只有一個(gè)線(xiàn)程訪(fǎng)問(wèn)的情況下廣泛使用。
存取器控制
readwrite(默認(rèn)):readwrite是默認(rèn)值,表示該屬性同時(shí)擁有setter和getter。
readonly: readonly表示只有g(shù)etter沒(méi)有setter。
有時(shí)候?yàn)榱苏Z(yǔ)意更明確可能需要自定義訪(fǎng)問(wèn)器的名字:
@property (nonatomic, setter = mySetter:,getter = myGetter ) NSString *name;
最常見(jiàn)的是BOOL類(lèi)型,比如標(biāo)識(shí)View是否隱藏的屬性hidden??梢赃@樣聲明:
@property (nonatomic,getter = isHidden ) BOOL hidden;
內(nèi)存管理
strong? ? ? ? ? ? ? 釋放舊對(duì)象將舊對(duì)象的值賦予輸入對(duì)象,再提高輸入對(duì)象的索引計(jì)數(shù)為1,此關(guān)鍵字經(jīng)常使用。
weak? ? ? ? ? ? ? ? 不增加引用計(jì)數(shù),不持有對(duì)象,因此也不能決定對(duì)象釋放? 對(duì)比assign 的一個(gè)好處是,當(dāng)對(duì)象消失時(shí)指針自動(dòng)歸為nil
assign? ? ? ? ? ? ? 適用于基礎(chǔ)數(shù)據(jù)類(lèi)型(NSInteger CGFloat...)不增加引用計(jì)數(shù)
copy? ? ? ? ? ? ? ? 建立一個(gè)索引計(jì)數(shù)為1 的對(duì)象然后釋放舊對(duì)象 此屬性只對(duì)那些實(shí)行了NSCopying協(xié)議的對(duì)象類(lèi)型有效(NSString , Block)
如果聲明屬性的時(shí)候不顯式指定任何關(guān)鍵字的時(shí)候默認(rèn)的關(guān)鍵字分兩種,一種是基本數(shù)據(jù)類(lèi)型的默認(rèn)關(guān)鍵字是atomic,readwrite,assign,第二種對(duì)于普通的OC對(duì)象,默認(rèn)關(guān)鍵字是atomic,readwrite,strong。
同時(shí)重寫(xiě)setter/getter的問(wèn)題:我們會(huì)發(fā)現(xiàn),當(dāng)我們同時(shí)重寫(xiě)setter/getter時(shí)會(huì)報(bào)錯(cuò),為什么呢?這是因?yàn)楫?dāng)我們同時(shí)重寫(xiě)setter/getter時(shí),編譯器自動(dòng)添加的代碼@synthesize dataArray = _dataArray;失效,就不會(huì)自動(dòng)為我們生成實(shí)例變量_dataArray了,setter/getter操作的對(duì)象就不存在了。所以我們要加上@synthesize dataArray = _dataArray;,手動(dòng)指定setter/getter要操作的實(shí)例對(duì)象是_dataArray.
2.@synthesizer
實(shí)現(xiàn)property所聲明的方法的定義。其實(shí)說(shuō)直白就像是:property聲明了一些成員變量的訪(fǎng)問(wèn)方法,synthesize則定義了由property聲明的方法。
他們之前的對(duì)應(yīng)關(guān)系是:property 聲明方法 ->頭文件中申明getter和setter方法 synthesize定義方法 -> m文件中實(shí)現(xiàn)getter和setter方法。
@interface ViewController ()
@property (nonatomic, strong) UIButton *myButton;
@end
@implementation ViewController
@synthesize myButton ;
@synthesize 語(yǔ)句只能被用在 @implementation 代碼段中,@synthesize 還有一個(gè)作用,可以指定與屬性對(duì)應(yīng)的實(shí)例變量,例如@synthesize myButton = xxx;那么self.myButton其實(shí)是操作的實(shí)例變量xxx,而不是_myButton了。如果默認(rèn)沒(méi)寫(xiě)@synthesize和 @dynamic都沒(méi)寫(xiě),那么默認(rèn)的就是@syntheszie var = _var;
3.@dynamic
@dynamic 告訴編譯器:屬性的 setter 與 getter 方法由用戶(hù)自己實(shí)現(xiàn),不自動(dòng)生成。(當(dāng)然對(duì)于 readonly 的屬性只需提供 getter 即可)。假如一個(gè)屬性被聲明為 @dynamic var,然后你沒(méi)有提供 @setter方法和 @getter 方法,編譯的時(shí)候沒(méi)問(wèn)題,但是當(dāng)程序運(yùn)行到 instance.var = someVar,由于缺 setter 方法會(huì)導(dǎo)致程序崩潰;或者當(dāng)運(yùn)行到 someVar = var 時(shí),由于缺 getter 方法同樣會(huì)導(dǎo)致崩潰。編譯時(shí)沒(méi)問(wèn)題,運(yùn)行時(shí)才執(zhí)行相應(yīng)的方法,這就是所謂的動(dòng)態(tài)綁定。
參考:
http://blog.eddie.com.tw/2010/12/08/property-and-synthesize/
http://www.cocoachina.com/bbs/read.php?tid=7322
http://www.cnblogs.com/pinping/archive/2011/08/03/2126150.html