objc推薦咱們經過set/get方法訪問對象的屬性。很顯然,爲每個屬性手動添加set/get方法的聲明和實現是個性價比很低的重複勞動。所以,objc提供了一些關鍵字幫助咱們簡化這一過程。實際上就是這麼回事兒。html
首先來看如今的property:xcode
例如:bash
@interface ViewController : UIViewController
@property (nonatomic,assign) BOOL testVar;
@end
複製代碼
簡單理解,至關於聲明瞭成員變量_testVar
,聲明瞭實現了set方法setTestVar
、get方法testVar
,等價於:app
@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方法的實現。ide
默認地,@synthesize會生成一個同名的成員變量做爲set/get的目標。ui
例如:this
@interface ViewController : UIViewController
@property (nonatomic,assign) BOOL testVar;
@end
@implementation ViewController
@synthesize testVar;
@end
複製代碼
等價於:atom
@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
。spa
注意,不少人誤認爲@synthesize默認生成的成員變量是_testVar
,據我所知這是不對的。code
官方文檔:
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的一些機制動態插入。這裏有一些例子。
通常開發中基本上不會用到。