目錄
- 歷史由來
- @dynamic與@synthesize的區(qū)別
- 總結
一 歷史由來
在 iOS5之前彼宠,屬性的正常寫法需要三個步驟
- 成員變量
- @property
- @synthesize
實例代碼
@interface ViewController () {
// 1.聲明成員變量
NSString *name;
}
// 2.用@property
@property(nonatomic, copy)NSString *name;
@end
@implementation ViewController
// 3.最后在@implementation中用synthesize生成set方法
@synthesize name;
如果漏寫了 @synthesize
,則編譯時會有警告
Autosynthesized property 'name' will use synthesized instance variable
'_name', not existing instance variable 'name'
在iOS5之后慎冤,蘋果推出一個新機制睡腿,@property聲明的屬性默認會生成一個_類型的成員變量,同時也會生成setter/getter方法藻三。
其實鳞陨,發(fā)生這種狀況根本原因是蘋果將默認編譯器從GCC
轉換為LLVM(low level virtual machine)
颠猴,才不再需要為屬性聲明實例變量了。
更換為LLVM之后坡贺,編譯器在編譯過程中發(fā)現(xiàn)沒有新的實例變量后官辈,就會生成一個下劃線開頭的實例變量
。因此現(xiàn)在我們不必在聲明一個實例變量遍坟。(注意:是不必要拳亿,不是不可以
)
在.m文件中,編譯器也會自動的生成一個實例變量_name
愿伴。那么在.m文件中可以直接的使用_name
實例變量风瘦,也可以通過屬性self.name
都是一樣的。
注意這里的self.myString其實是調用的myString屬性的setter/getter方法公般。這與C++中點的使用是有區(qū)別的万搔,C++中的點可以直接訪問成員變量(也就是實例變量)。
實戰(zhàn)檢驗
1.直接聲明成員變量
@interface ViewController () {
NSString *name;
}
@end
在這段代碼里面只是聲明了一個成員變量官帘,并沒有setter/getter方法瞬雹。所以訪問成員變量時,可以直接訪問name刽虹,也可以像C++一樣用self->name來訪問酗捌。
// 訪問1
name = @"韓雪";
NSLog(@"name = %@",name);
// 訪問e2
self->name = @"孫悟空";
NSLog(@"name = %@",self->name);
打印結果
但絕對不能用self.name來訪問
self.name = @"韓雪";
會直接報錯
擴展:很多人覺得OC中的點語法比較奇怪,實際是OC設計人員有意為之涌哲。
- 點表達式(.)看起來與C語言中的結構體訪問以及java語言匯總的對象訪問有點類似胖缤,如果點表達式出現(xiàn)在等號=左邊,調用該屬性名稱的setter方法阀圾。如果點表達式出現(xiàn)在=右邊哪廓,調用該屬性名稱的getter方法。
- OC中點表達式(.)其實就是調用對象的setter和getter方法的一種快捷方式初烘,self.myString = @"張三";實際就是[self setmyString:@"張三"];
首先我們要明白涡真,@synthesize生成了setter/getter方法。
雖然現(xiàn)在直接使用@property時肾筐,編譯器會自動為你生成以下劃線開頭的實例變量_myString哆料,不需要自己手動再去寫實例變量。而且也不在.m文件中通過@synthesize myString吗铐;生成setter/getter方法东亦。但在看老代碼的時候,我們依舊可以看到有人使用成員變量+ @synthesize成員變量的形式唬渗。
@synthesize還有一個作用典阵,可以指定與屬性對應的實例變量奋渔,
例如@synthesize name = xxx;
那么self.name其實是操作的實例變量xxx萄喳,而非_name了卒稳。
- 實例代碼1
@synthesize name = myName;
self.name = @"韓雪";
NSLog(@"_name = %@",self->_name);
打印結果
- 實例代碼2
@synthesize name = myName;
self.name = @"韓雪";
NSLog(@"_myName = %@",self->myName);
打印結果
二 @dynamic與@synthesize的區(qū)別
2.1 @dynamic
dynamic告訴編譯器蹋半,不自動生成getter/setter方法他巨,
- 實例代碼
@interface ViewController ()
@property(nonatomic, copy)NSString *name;
@end
@implementation ViewController
@dynamic name;
- (void)viewDidLoad {
[super viewDidLoad];
self.name = @"韓雪";
NSLog(@"name = %@",self.name);
}
@end
運行結果 - 直接崩潰,報方法找不到的錯誤
2.2 @synthesize
@synthesize編譯器期間减江,讓編譯器自動生成getter/setter方法染突。
當有自定義的存或取方法時,自定義會屏蔽自動生成該方法
- 實例代碼
@synthesize name = _myName;
- (void)viewDidLoad {
[super viewDidLoad];
self.name = @"韓雪";
NSLog(@"name = %@",self.name);
}
// 自定義 set 方法
- (void)setName:(NSString *)name {
_myName = @"孫悟空";
}
// 自定義 get方法
- (NSString *)name {
return _myName;
}
打印結果
總結
- 成員變量
1. 成員變量的默認修飾是@protected辈灼。
2. 成員變量不會自動生成set和get方法份企,需要自己手動實現(xiàn)。
3. 成員變量不能用點語法調用巡莹,因為沒有set和get方法司志,只能使用->調用。
- 屬性
1. 屬性的默認修飾是@protected降宅。
2. 屬性會自動生成set和get方法骂远。
3. 屬性用點語法調用,點語法實際上調用的是set和get方法腰根。