今天就來寫寫一直以來想要搞懂部分 Objective-C的Declared Properties。
其實要寫iOS程式,Declared Properties是很基本的,但是由於我是從寫Mac程式就開始用Objective-C(1.x),Declared Properties 是Objective-C 2.0才有的,再加上之前不夠認真,所以不是很熟就憑印象加上依樣畫葫蘆(Copy & Paste)地把code寫出來了 ,實在不應該。所謂出來混,遲早要還的,於是就花一點時間認真看了一下Apple官方關於Objective-C的文件。印象中配合燈光美氣氛佳的環境大約一個小時應該可以看完。(讀者你可能不用,因為我有些微的閱讀障礙)
下面算是整理後的一些重點(順便備忘),建議讀者有需要還是自己看一下文件,才不會漏掉些被我忽略的細節。
節省你的時間
傳統物件導向的程式免不了要寫Accessor。寫久了還真浪費時間,浪費生命。所以Objective-C 2.0 就加進了Declared Properties。所以透過Declared Properties,在大部分的狀況下你就可以不用再寫Accessor了。
例子:
沒用Declared Properties的時候
@interface MyClass : NSObject { NSNumber *_myNumber; } // Accessor - Getter - (NSNumber *)myNumber; // Accessor - Setter - (void)setMyNumber:(NSNumber *)newNumber; @end @implementation MyClass // Accessor - Getter - (NSNumber *)myNumber { return _myNumber; } // Accessor - Setter - (void)setMyNumber:(NSNumber *)newNumber { if (newNumber != _myNumber) { [_myNumber release]; _myNumber = [newNumber retain]; } } @end是不是很麻煩!光寫完這個例子我就有點後悔開始寫這篇文章了。(這個例子還是簡易版的了,有時候為了解決某些狀況還會變更複雜,例如考慮Thread-Safety的問題)
用Declared Properties之後
@interface MyClass : NSObject @property(retain) myNumber; @end @implementation MyClass @synthesize myNumber @end
語法-宣告
宣告一個Property的語法大概是長這樣
@property (attributes) type name;
例如:
@property float value;
很簡短吧!比較複雜的部分是你要瞭解裡面attributes有哪些,又分別代表什麼意義。
Accessor Method Names
Objective-C 提供給你可以設定Accessor名稱的Attribute:
- getter=getterName
- setter=setterName
根據Objective-C的慣例,你不太需要去更改預設的名稱。比較常見的需要是為了讓語意更通順。例如你的Class有一個型別為BOOL而名稱叫hidden的Property,如果你沒有去更改預設的Getter,你得用[obj hidden]這樣的寫法去讀取這個值,然後就會產生下面的Code
if ([theView hidden]) { [theView setHidden:NO]; }
讀起來會有點怪怪的。
如果你透過getter=(isHidden)去更改預設Getter名稱就可以讓Code讀起來更順了。
if ([theView isHidden]) { [theView setHidden:NO]; }
Writability
Objective-C 提供Attribute讓你定義該Property是否為可寫:
- readwrite(預設)
- readonly
Setter Semantics
Objective-C 提供Attribute讓你定義Setter的Semantics(語意?):
- strong
- weak
- copy
- assign(預設)
- retain
其中strong跟weak還不是很確定,需要再研究一下。
之前比較常用的是copy, assign與retain。
copy代表setter會複製傳進來的物件。
assign的話只會把傳進來的物件assign給property而不會增加它的retain count,通常會用在delegate的設計去避免造成cross retain導致兩個物件互相擁有,然後抱在一起就不會死了。
retain的話就會retain傳進來的物件。
所以要根據你的設計好好挑選你要的。
Atomicity
為了在Multithread的環境能後正常運作(Thread Safety),Objective-C Property的Accessor預設是atomic的。
我想除了效能上的考量同時又沒有Thread Safety的問題的話,才會考慮透過nonatomic這個Attribute去讓改Property的Accessor變成nonatomic。
語法-實作
在宣告完之後,就剩實作了。
你可以二選一,決定你實作的方式:
- @synthesize
- @dynamic
@synthesize 就是叫Compiler幫你合成Accessor就是叫Compiler幫你生成instance variable。
@dynamic 就是跟Compiler講你要自己寫Accessor。最常見的例子就是在用Core Data時實作Model Object的部分。因為Core Data的Model Object都是繼承自NSManagedObject,而NSManagedObject的Attribute的Accessor也都準備好了(透過KVC),所以你既不用自己寫Accessor也不用(也不可以)透過@synthesize叫Compiler幫你合成Accessor。 就是跟Compiler說instance variable的問題你會自己傷腦筋。最常見的例子就是Core Data的Model Object的部分。因為property的部分都被NSManagedObject給處理好了,所以不用另外生成對應的instance variable,所以用@dynamic就好。
strong, weak 是有Xcode 4.3 ARC(auto reference counting)才開始的!詳細的如何應用區分也是要再花時間鑽研,但總之,我自己的解讀(maybe not exactly right)是,那些在整個App執行的過程裡,都不太需要dealloc的東西,就是給他用strong便是。
回覆刪除感謝你的回覆 :)
刪除有機會也要來看一下ARC
dynamic 原來是這樣阿~
回覆刪除