objc推薦咱們經過set/get方法訪問對象的屬性。很顯然,爲每個屬性手動添加set/get方法的聲明和實現是個性價比很低的重複勞動。所以,objc提供了一些關鍵字幫助咱們簡化這一過程。實際上就是這麼回事兒。html
首先來看如今的property:xcode
例如:app
@interface ViewController : UIViewController @property (nonatomic,assign) BOOL testVar; @end
簡單理解,至關於聲明瞭成員變量_testVar
,聲明瞭實現了set方法setTestVar
、get方法testVar
,等價於:ide
@interface ViewController : UIViewController { BOOL _testVar; } - (void)setTestVar:(BOOL)newTestVar; - (BOOL)testVar; @end @implementation ViewController - (void)setTestVar:(BOOL)newTestVar { _testVar = newTestVar; } - (BOOL)testVar { return _testVar; } @end
@synthesize能夠指定set/get方法的實現。ui
默認地,@synthesize會生成一個同名的成員變量做爲set/get的目標。this
例如:atom
@interface ViewController : UIViewController @property (nonatomic,assign) BOOL testVar; @end @implementation ViewController @synthesize testVar; @end
等價於:code
@interface ViewController : UIViewController { BOOL testVar; } - (void)setTestVar:(BOOL)newTestVar; - (BOOL)testVar; @end @implementation ViewController - (void)setTestVar:(BOOL)newTestVar { testVar = newTestVar; } - (BOOL)testVar { return testVar; } @end
能夠看到,set/get方法指向了成員變量testVar
,也不會再默認生成_testVar
。htm
注意,不少人誤認爲@synthesize默認生成的成員變量是_testVar
,據我所知這是不對的。對象
官方文檔:
Important: If you use
@synthesize
without specifying an instance variable name, like this:@synthesize firstName;the instance variable will bear the same name as the property.
In this example, the instance variable will also be called
firstName
, without an underscore.
@synthesize也能夠指定一個成員變量做爲其set/get的目標。
例如:
@interface ViewController : UIViewController { BOOL exampleVar; } @property (nonatomic,assign) BOOL testVar; @end @implementation ViewController @synthesize testVar = exampleVar; @end
等價於:
@interface ViewController : UIViewController { BOOL exampleVar; } - (void)setTestVar:(BOOL)newTestVar; - (BOOL)testVar; @end @implementation ViewController - (void)setTestVar:(BOOL)newTestVar { exampleVar = newTestVar; } - (BOOL)testVar { return exampleVar; } @end
此時set/get方法就指向了成員變量exampleVar
。
特別的,能夠聲明並指定成員變量_testVar
,例如:
@interface ViewController : UIViewController { BOOL _testVar; } @property (nonatomic,assign) BOOL testVar; @end @implementation ViewController @synthesize testVar = _testVar; @end
這是最符合官方規範的作法:每一個屬性對應一個以_
開頭的成員變量。
能夠看出,這種寫法跟本文第一部分,只寫一個@property
的做用是同樣的。
其實,在xcode4.4(對應clang3.2/LLVM4.0)之前,顯式聲明_testVar
和@synthesize testVar = _testVar;
是標準作法。那時候只寫個@property
並不會給你帶來成員變量和set/get的實現。
如今的表現是編譯器把之前的標準作法化做默認行爲的結果。當咱們只聲明瞭@property
而沒有實現對應的set/get方法時,編譯器會默認聲明_
開頭的成員變量並補全set/get的實現。
最近遇到的問題是一坨老代碼,裏面用了@synthesize
可是彷佛不是很規範,後來維護的人看起來也不太熟悉這幾個關鍵字,照着前人的代碼瞎寫,最後代碼相似下面的:
@interface ViewController : UIViewController { BOOL _testVar; } @property (nonatomic,assign) BOOL testVar; @end @implementation ViewController @synthesize testVar; - (void)viewDidLoad { [super viewDidLoad]; self.testVar = YES; if(_testVar){ [self doSomething]; } } @end
能夠看到,代碼邏輯裏用_testVar
去作條件判斷實際上是徹底無效的。
@dynamic的做用是告訴編譯器,此屬性對應的set/get方法將會被動態提供。
說得明白一點,其實@dynamic作了兩件事:
一般若是用到dynamic的話,這些方法會在消息轉發的時候處理,也能夠經過runtime的一些機制動態插入。這裏有一些例子。
通常開發中基本上不會用到。