1. 程式人生 > >Objective-C中.h檔案、.m檔案中@interface、@synthesize及其它

Objective-C中.h檔案、.m檔案中@interface、@synthesize及其它

很多開發iOS好幾年的老鳥,可能都不太分的清.h檔案和.m檔案裡各種結構的用途和區別。最近仔細研究了一下,寫一篇文章記下來。 
一般的,寫一個Class的時候,經常是這種格式(以UIViewController為例):

.h檔案:

@interface ClassName{
    NSString* _value1;
}

@property(nonatomic,assign)NSString* value1; -(void)func1;

.m檔案:

@interface ClassName(){
}
@end @synthesize value1; @implementation ClassName -(void)func1{ } @end

大體上就是這個格式。很多人,包括我,在建立和使用Class時,直接就使用這樣的模板。這個模板裡有一些有意思的小東西,值得探討,比如: 
1. 為什麼.h檔案和.m檔案裡各有1個@interface?它們分別有什麼用? 
2. .h中,value1為什麼要定義2遍? 
3. @synthesize有什麼用? 
還有一些其它的問題,今天先解決上面提到的這幾個。

為什麼.h檔案和.m檔案裡各有1個@interface?它們分別有什麼用?

.h裡面的@interface,不消說,是典型的標頭檔案,它是供其它Class呼叫的。它的@property

和functions,都能夠被其它Class“看到”。

而.m裡面的@interface,在OC裡叫作Class Extension,是.h檔案中@interface的補充。但是.m檔案裡的@interface,對外是不開放的,只在.m檔案裡可見。

因此,我們將對外開放的方法、變數放到.h檔案中,而將不想要對外開放的變數放到.m檔案中(.m檔案的方法可以不宣告,直接用)。

有的同學看到Class Extension,可能會想到OC裡的@protocol。是的,它們都是對一個Class的擴充套件。不過它們的區別也很明顯:

Class Extension只能用在能得到原始碼的情況下,而@protocol

在得不到原始碼的時候也可以使用。

因此@protocol一般用作對一些系統Class的擴充套件,常見的比如對NSString、UIView等。

.h中,value1為什麼要定義2遍?

當然,現在@interface{}裡的定義也可以省略掉了,不過原理還是要搞清楚。

嚴格來說@interface{}裡定義的變數,叫作instance variable,它是這個Class內部真正的全域性變數。然而這個instance variable是不對外公開的,因此我們還需要一個對外公開的東西來呼叫,就是@property 
@property是對外的,它其實是告訴大家,我這個Class裡,有一個變數的set/get方法。比如,@property NSString* string; 就是說,本Class裡有一個getString/setString供你們呼叫。

因此需要2次宣告。當然現在lldb也升級了,只要你聲明瞭@property,它就可以自動建立對應的全域性變數。

@synthesize有什麼用?

@property 一個變數後,在@implementation裡再@synthesize一下,相信是很多人的習慣。但是為什麼要有這個@synthesize方法呢?

@property是對外聲明瞭Class的get/set方法,然後我們就需要在.m檔案裡手寫get/set方法。這可就麻煩了,1個變數對應2個方法,假如一個Class裡有10個變數,那豈不是要寫20個方法?煩也煩死嘮。

@synthesize幫我們解決了這個問題。@synthesize在.m檔案裡自動生成了get/set方法。因此,我們只要在@implementation後面加上一行:@synthesize 就可以自動生成get/set方法了,省掉了很多麻煩。比如@synthesize value1 = _value1;的意思就是,將instance variable _value1用作getValue1和setValue1方法裡。

get/set方法有時候是比較複雜的,因為它和變數的屬性相關,就是@property(nonatomic, assign/retain(strong/weak))這就和記憶體有關了。然而@synthesize為我們做了這些事情,就不要再為這些事情煩惱了!

更方便的是,從Xcode4.4開始,編譯器會自動為每一條@property都新增一條對應的@synthesize,因此以後我們只要寫一個@property就可以了!