IOS,objective_C中用@interface和 @property 方式宣告變數的區別
一直有疑問,在objective_C中宣告變數會有 2種方式,今天有空和網友討論了下,並且自己查了stackoverflew後算是稍微弄懂了一點。記錄如下:
用了一段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 6 @property (assign, readonly) BOOL gameCenterAvailable;
而且你可以單獨在@interface中定義變數,而不用@property定義;也可以只用@property去定義,而不在@interface中定義,當然用了@property去定義,一般要在.m檔案中用@synthsize去合成相應的setter,getter方法。否則會得到一個警告。當然@synthsize是可選的,但是是Apple推薦的,不用會有什麼後果,我沒試過,有興趣的童鞋可以試一下。
那這兩種方式有什麼區別呢。
1. 只在@interface中定義變數的話,你所定義的變數只能在當前的類中訪問,在其他類中是訪問不了的;而用@property宣告的變數可以在外部訪問。
2.用了@property去宣告的變數,可以使用“self.變數名”的方式去讀寫變數。而用@interface的方式就不可以。
Defining the variables in the brackets simply declares them instance variables.
在括號中定義一個變數只是簡單的聲明瞭一個例項變數(例項變數應該指的成員變數)。 博主注:老外對variable 和instance variable是有不同理解的。所以下文中 用了一個模糊的詞 ivar。
Declaring (and synthesizing) a property generates getters and setters for the instance variable, according to the criteria within the parenthesis. This is particularly important in Objective-C because it is often by way of getters and setters that memory is managed (e.g., when a value is assigned to an ivar, it is by way of the setter that the object assigned is retained and ultimately released). Beyond a memory management strategy, the practice also promotes encapsulation and reduces the amount of trivial code that would otherwise be required.
宣告(和 @synthsize)一個屬性會為成員變數生成 getter 和setter方法,根據括號內的標準,在oc中經常用setter和getter 做記憶體管理,這是很重要的。(例如: 當一個值被賦給這個變數,物件是通過setter函式去分配,修改計數器,並最後釋放的)。更高一個層次來說,這種做法也促進了封裝,減少了一些不必要的程式碼。
It is very common to declare an ivar in brackets and then an associated property (as in your example), but that isn't strictly necessary. Defining the property and synthesizing is all that's required, because synthesizing the property implicitly also creates an ivar.
在@interface括號中定義一個變數並用@property 重複定義一次是很普遍的,實際上不是必要的。用@property和@synthszie就夠了,因為在用@synthsize合成這個屬性的讀寫方法時就會建立一個變數。
The approach currently suggested by Apple (in templates) is:
目前蘋果(在模板中)建議的方法是這樣的:
-Define property in header file, e.g.:
先在標頭檔案中定義一個屬性
1 @property int gameCenter;
Then synthesize & declare ivar in implementation:
然後在實現檔案中 synthsize和declare成這樣:
1 @synthesize gameCenter = __ gameCenter;
The last line synthesizes the gameCenter property and asserts that whatever value is assigned to the property will be stored in the __gameCenter ivar. Again, this isn't necessary, but by defining the ivar next to the synthesizer, you are reducing the locations where you have to type the name of the ivar while still explicitly naming it.
最後一行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 { 3 return _gameCenter; 4 }
而直接寫 @synthsize gameCenter;
setter函式會在內部展開成
1 -(int)gameCenter 2 { 3 return gameCenter; 4 }
注意到:函式名和變數名是一樣的。在斯坦福的課程中,白鬍子教授也模糊的說道這樣的同名有可能帶來bug,具體什麼bug他沒說,我也沒見過,所以還是養成這樣寫的習慣為好。其他語言的getter函式 一般會在變數前加 get;但oc沒有,可能是為了與其他語言做區分,算是oc的特色,結果卻帶來這麼個麻煩。