天天看點

【IOS】@interface和 @property 方式聲明變量的差別

在IOS程式設計中,很多人沒有了解執行個體變量與屬性的差別,我根據自己的經驗,這這裡與大家分享下這裡面的差別,下面我寫一個簡單的例子:

.h

1 @interface MyController :UIViewController
2 {
3   UILabel *_myLabel;//這裡是執行個體變量聲明
4 }
5 
6 @property (nonatomic, retain) UILabel*myLabel;//這裡是你的屬性聲明
7 
8 @end      

.m

1 @implementation MyController
2 
3 @synthesize myLabel = _myLabel;
4 
5 ...
6 
7 @end      

相信大家都看到過這樣的程式,但我們一般寫的程式是下面這樣子的:

.h

1 @interface MyController :UIViewController
2 {
3   UILabel *myLabel;//這裡是執行個體變量聲明
4 }
5 
6 @property (nonatomic, retain) UILabel*myLabel;//這裡是你的屬性聲明
7 
8 @end      

.m

1 @implementation MyController
2 
3 @synthesize myLabel;
4 
5 ...
6 
7 @end      

其實,執行個體變量跟屬性在cocoa裡面應該是分開的,而下面這種我們平時寫的這種代碼因為實力變量跟屬性是同一個名字,是以就不用使用等号來把執行個體變量指派給屬性了,執行個體變量一般是用在一個類的内部,而我們平時用的時候會在其他的類裡面建立另一個類的對象,比如我們想改變我們上面建立的這個類的myLabel的text屬性,這時,我們使用的是什麼呢?要講清楚這個問題,使用我們最上面的那段代碼是最好的,現在我們假設已經建立了MyController的一個對象,叫做myController,要改變myLabel的text應該如下:

1 myController.myLabel.text =@"這是改變了之後的内容";      

看清楚,這裡使用的是myLabel(屬性),不是_myLabel(執行個體變量),在MyController這個類裡面"self."的時候也隻能屬性,執行個體變量都是assign類型的,你需要直接alloc記憶體指派給它,同樣在最後dealloc裡面的release的也是執行個體變量而非屬性,屬性其實就是在外部或者内部調用時候使用執行個體變量的一種方式(個人了解),而真正占用記憶體的卻是執行個體變量。

用了一段oc;會發現有2種定義變量的方式

      1.在  @interface :NSObject{} 的括号中,當然NSObject 是指一個父類,可以是其他的。

      形式如下:

1 @interface GCTurnBasedMatchHelper : NSObject {
2    BOOL gameCenterAvailable;
3    BOOL userAuthenticated;
4 }      

   2.另外一種是直接在 @interface : NSObject{}括号之後,用 @property 去定義一個變量。

1  @property (assign, readonly) BOOL gameCenterAvailable;      

  你會發現,有人會再@interface中定義了變量後,又在 @property中重複定義相同的變量,而且很常見。

  結果可能是這樣:

1 @interface GCTurnBasedMatchHelper : NSObject {
2    BOOL gameCenterAvailable;
3    BOOL userAuthenticated;
4 }
5 @property (assign, readonly) BOOL gameCenterAvailable;      

  而且你可以單獨在@interface中定義變量,而不用@property定義;也可以隻用@property去定義,而不在@interface中定義,當然用了@property去定義,一般要在.m檔案中用@synthsize去合成相應的setter,getter方法。否則會得到一個警告。當然@synthsize是可選的,但是是Apple推薦的,不用會有什麼後果,我沒試過,有興趣的童鞋可以試一下。

     那這兩種方式有什麼差別呢?

    1. 隻在@interface中定義變量的話,你所定義的變量隻能在目前的類中通路,在其他類中是通路不了的;而用@property聲明的變量可以在外部通路。

    2.用了@property去聲明的變量,可以使用“self.變量名”的方式去讀寫變量。而用@interface的方式就不可以。

這裡給出一個連結:http://stackoverflow.com/questions/9702258/difference-between-properties-and-variables-in-ios-header-file裡面講到:我英語菜,簡單翻一下:

在括号中定義一個變量隻是簡單的聲明了一個執行個體變量(執行個體變量應該指的成員變量)。  部落客注:老外對variable 和instance variable是有不同了解的。是以下文中 用了一個模糊的詞 ivar。

聲明(和 @synthsize)一個屬性會為成員變量生成 getter 和setter方法,根據括号内的标準,在oc中經常用setter和getter 做記憶體管理,這是很重要的。(例如: 當一個值被賦給這個變量,對象是通過setter函數去配置設定,修改計數器,并最後釋放的)。更高一個層次來說,這種做法也促進了封裝,減少了一些不必要的代碼。

在@interface括号中定義一個變量并用@property 重複定義一次是很普遍的,實際上不是必要的。用@property和@synthszie就夠了,因為在用@synthsize合成這個屬性的讀寫方法時就會建立一個變量。

重點是下面紅色字型!!!!!或者看千鋒3G文法知識第二講後半部分有講。

目前蘋果(在模闆中)建議的方法是這樣的:

先在頭檔案中定義一個屬性

@property int gameCenter;

然後在實作檔案中  synthsize和declare成這樣:

@synthesize gameCenter = __ gameCenter;

最後一行synthsize  gameCenter 屬性并說明了不管什麼值被配置設定給這個屬性,都會存儲到_gameCenter這個變量中。 再次說明,這不是必要的,但是,這樣寫了之後,你能減少輸入已經明确命名的變量名。

最後一句的意思you are reducing the locations where you have to type the name of the ivar while still explicitly naming it .不好翻。

據千鋒的第2節文法課課程的講解,這樣寫之後可以使得 @synthsize 時内部getter方法會展成

1 -(int)gameCenter {
2     return _gameCenter;
3 }      

而直接寫  @synthsize  gameCenter;

setter函數會在内部展開成

1 -(int)gameCenter {
2   return gameCenter;
3 }      

  注意到:函數名和變量名是一樣的。在斯坦福的課程中,白胡子教授也模糊的說道這樣的同名有可能帶來bug,具體什麼bug他沒說,我也沒見過,是以還是養成這樣寫的習慣為好。其他語言的getter函數  一般會在變量前加 get;但oc沒有,可能是為了與其他語言做區分,算是oc的特色,結果卻帶來這麼個麻煩。

轉載于:https://www.cnblogs.com/DannyApple/p/3931359.html

繼續閱讀