OC屬性與實例變數 無論是java還是c++這些面向對象的語言都會有屬性這一概念,通常而言,對於java屬性和實例變數沒有什麼區別,java官方定義的屬性如下: 屬性是指get或者set方法名 去掉get或者set後,把剩餘的部分首字母改為小寫後,即為這個類的 屬性 其實objective C與之類 ...
OC屬性與實例變數
無論是java還是c++這些面向對象的語言都會有屬性這一概念,通常而言,對於java屬性和實例變數沒有什麼區別,java官方定義的屬性如下:
屬性是指get或者set方法名 去掉get或者set後,把剩餘的部分首字母改為小寫後,即為這個類的屬性
其實objective-C與之類似,但是在一般的開發中,oc類的實例變數都不會被直接讀寫,而是通過getter和setter方法來進行讀寫操作。原因如下:
-
直接讀寫實例變數實質上是在編譯的過程中,對.h文件中聲明的各個實例變數的偏移量進行操作。眾所周知,OC屬於運行時的動態語言。如果在運行時再添加實例變數,則原來的實際偏移量就會出現錯誤,記憶體佈局的改變會導致直接讀寫實例變數出現錯誤。
但是如果將實例變數的讀寫修改為通過getter和setter方式的通知(OC的方法可看作為消息傳遞),而這些對象方法則存於類對象中,這樣就可以解決上述問題。
OC將實例變數當作一種存儲偏移量所用的“特殊變數”,並將其交給類對象來進行保管,這樣做的好處就是系統會在運行期進行查找,若類的定義在運行期改變了,那麼存儲的偏移量也就隨之改變。
-
通過setter方法來修改類的實例變數,還可以觸發屬性的KVO。如果是直接改變實例變數,則無法觸發。
屬性的自動合成
使用 @property+類型名+屬性名 可以讓編譯器自動編寫這些屬性需要的方法。
例如:
@property NSString *autoCreatedStr
在添加了property關鍵字後,編譯器會自動合成以下的setter和getter方法:
- (void) setAutoCreatedStr:(NSString *)autoCreatedStr;
- (NSString *) autoCreatedStr;
在自動合成屬性前,編譯器會自動為屬性提供對應的實例變數,實例變數通常以下劃線開頭+屬性名:
NSString *_autoCreatedStr;
@synthesize關鍵字
在iOS6之前,編譯器是不會在設置完@Property後自動生成實例變數的,當設置完屬性後還要額外再加上一句:
@synthesize autoCreatedStr = _autocreatedStr;
加上這句以後,才能完成添加名為“_autoCreatedStr”的實例變數。
但是在iOS6以後,LLVM編譯器就會為每個屬性添加上對應的@synthesize關鍵字,並且預設實例名為:下劃線開頭+屬性名的格式。
所以在一般的開發中,只有想要自定義實例變數名的時候,才會在.m文件中手動添加@synthesize來覆蓋原來的自動合成的以下劃線開頭的變數名。(一般來說都無需修改預設的實例變數名)
@dynamic關鍵字
dynamic關鍵字主要是用來通知編譯器無需因為@property關鍵字而自動合成屬性(包括生成實例變數和合成getter、setter方法)。
在編譯的過程中,編譯器不會因為沒有定義讀寫方法而報錯,因為@dynamic關鍵字預設了讀寫方法會在運行時生成。例如在分類中利用關聯對象來給分類添加屬性等。
總結
- OC開發中,通常不會直接對實例變數操作,而是通過getter和setter方法來對實例變數來進行讀寫。
- ios6後property關鍵字會自動合成實例變數和讀寫方法。
- dynamic關鍵字大部分情況其實用不到。