目錄:
1.簡述編譯器的變化對@property的影響;
2.實際使用中@property和成員變量+ @property + @synthesize 成員變量
的區別
3.self.XXX
,_XXX
,self->XXX
的區別;
4.Demo地址
歷史由來:
接觸iOS的人都知道,@property
聲明的屬性默認會生成一個_類型的成員變量,同時也會生成setter/getter
方法。
但這只是在iOS5之后,蘋果推出的一個新機制。看老代碼時,經常看到一個大括號里面定義了成員變量,同時用了@property聲明,而且還在@implementation中使用@synthesize
方法。
如下:
@interface ViewController ()
{
// 1.聲明成員變量
NSString *myString;
}
//2.在用@property
@property(nonatomic, copy) NSString *myString;
@end
@implementation ViewController
//3.最后在@implementation中用synthesize生成set方法
@synthesize myString;
@end
其實,發生這種狀況根本原因是蘋果將默認編譯器從GCC轉換為LLVM(low level virtual machine
),才不再需要為屬性聲明實例變量了。
在沒有更改之前,屬性的正常寫法需要成員變量+ @property + @synthesize 成員變量
三個步驟。
如果我們只寫成員變量+ @property
@interface GBViewController :UIViewController
{
NSString *myString;
}
@property (nonatomic, strong) NSString *myString;
@end
編譯時會報警告:
Autosynthesized property '?myString' will use synthesized instance variable '_myString', not existing instance variable 'myString''
但更換為LLVM之后,編譯器在編譯過程中發現沒有新的實例變量后,就會生成一個下劃線開頭的實例變量。因此現在我們不必在聲明一個實例變量。(注意:是不必要,不是不可以)
當然我們也熟知,@property
聲明的屬性不僅僅默認給我們生成一個_類型的成員變量,同時也會生成setter/getter
方法。
在.m
文件中,編譯器也會自動的生成一個實例變量_XXX
。那么在.m文件中可以直接的使用_XXX
實例變量,也可以通過屬性self. XXX
。
只是我們需要注意這里的self.XXX
實際是調用XXX
屬性的setter/getter
方法。這與C++中點的使用是有區別的,C++中的點可以直接訪問成員變量(也就是實例變量)。
例如在OC中有如下代碼
@interface MyViewController :UIViewController
{
NSString *name;
}
@end
在這段代碼里面只是聲明了一個成員變量,并沒有setter/getter
方法。所以訪問成員變量時,可以直接訪問name
,也可以像C++一樣用self->name
來訪問,但絕對不能用self.name
來訪問。
- 擴展:很多人覺得OC中的點語法比較奇怪,實際是OC設計人員有意為之。
點表達式(.)
看起來與C語言中的結構體訪問以及java語言匯總的對象訪問有點類似,如果點表達式出現在等號=
左邊,調用該屬性名稱的setter
方法。如果點表達式出現在=
右邊,調用該屬性名稱的getter
方法。- OC中
點表達式(.)
其實就是調用對象的setter
和getter
方法的一種快捷方式,self.myString = @"張三";
實際就是[self setmyString:@"張三"];
首先我們要明白,@synthesize
生成了setter/getter
方法。
雖然現在直接使用@property
時,編譯器會自動為你生成以下劃線開頭的實例變量_myString
,不需要自己手動再去寫實例變量。而且也不在.m文件中通過@synthesize myString;
生成setter/getter
方法。但在看老代碼的時候,我們依舊可以看到有人使用成員變量+ @synthesize 成員變量
的形式。
那么問題來了:
我們能否認為新編譯器LLVM下的@property
== 老編譯器GCC的成員變量+ @property + @synthesize 成員變量
呢?
答案是否定的,
因為成員變量+ @property + @synthesize 成員變量
的形式,編譯器不會幫我們生成_成員變量
,因此不會操作_成員變量
了;
同時@synthesize
還有一個作用,可以指定與屬性對應的實例變量,
例如@synthesize myString = xxx;
那么self.myString
其實是操作的實例變量xxx,而非_String了。
在Demo中會有非常詳細的說明,歡迎下載和start。
寫在最后
我得寫作原則:
在技術學習道路上,閱讀量和代碼量絕不能線性提升你的技術水平。
同樣寫文章也是如此,作者所寫的文章完全是基于自己對技術的理解,在寫作時也力求形象不抽象。絕不copy充數,所以也歡迎大家關注和參與討論。
技術學習絕不能孤膽英雄獨闖天涯,而應在一群人的交流碰撞,享受智慧火花的狂歡。
希望我的文章能成為你的盛宴,也渴望你的建議能成為我的大餐。
如有錯誤請留言指正,對文章感興趣可以關注作者不定期更新。