2012年3月8日 星期四

Objective-C的Declared Properties

寫程式也有一段時間了(也有一段時間沒認真寫了 :P),也因此學了不少程式語言,一直都有一個“要寫好程式,最好把程式語言給搞懂”的體認。
今天就來寫寫一直以來想要搞懂部分 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就好。



3 則留言:

  1. strong, weak 是有Xcode 4.3 ARC(auto reference counting)才開始的!詳細的如何應用區分也是要再花時間鑽研,但總之,我自己的解讀(maybe not exactly right)是,那些在整個App執行的過程裡,都不太需要dealloc的東西,就是給他用strong便是。

    回覆刪除
    回覆
    1. 感謝你的回覆 :)
      有機會也要來看一下ARC

      刪除