一:屬性
@property = ivar + getter + setter;
編譯器會自動寫出一套存取方法活孩,用以訪問給定類型中具有給定名稱的變量。 所以你也可以這么說:
@property = getter + setter;
例如下面這個類:
@interface?Person?:?NSObject
@property?NSString?*firstName;
@property?NSString?*lastName;
@end
上述代碼寫出來的類與下面這種寫法等效:
@interface?Person?:?NSObject
-?(NSString?*)firstName;
-?(void)setFirstName:(NSString?*)firstName;
-?(NSString?*)lastName;
-?(void)setLastName:(NSString?*)lastName;
@end
完成屬性定義后,編譯器會自動編寫訪問這些屬性所需的方法良瞧,此過程叫做“自動合成”( autosynthesis)。需要強調(diào)的是,這個過程由編譯 器在編譯期執(zhí)行蹋偏,所以編輯器里看不到這些“合成方法”(synthesized method)的源代碼扮匠。除了生成方法代碼 getter肋殴、setter 之外枫弟,編譯器還要自動向類中添加適當類型的實例變量客燕,并且在屬性名前面加下劃線闺鲸,以此作為實例變量的名字澳骤。在前例中醋闭,會生成兩個實例變量鲤看,其名稱分別為 _firstName與_lastName。也可以在類的實現(xiàn)代碼里通過 @synthesize語法來指定實例變量的名字.
@implementation?Person
@synthesize?firstName?=?_myFirstName;
@synthesize?lastName?=?myLastName;
@end
@property有兩個對應的詞葫掉,一個是@synthesize些举,一個是@dynamic。如果@synthesize和@dynamic都沒寫俭厚,那么默認的就是@syntheszie var = _var;
@synthesize的語義是如果你沒有手動實現(xiàn)setter方法和getter方法户魏,那么編譯器會自動為你加上這兩個方法。
@dynamic告訴編譯器:屬性的setter與getter方法由用戶自己實現(xiàn)挪挤,不自動生成叼丑。(當然對于readonly的屬性只需提供getter即可)。假如一個屬性被聲明為@dynamic var扛门,然后你沒有提供@setter方法和@getter方法鸠信,編譯的時候沒問題,但是當程序運行到instance.var = someVar论寨,由于缺setter方法會導致程序崩潰星立;或者當運行到 someVar = var時,由于缺getter方法同樣會導致崩潰葬凳。編譯時沒問題绰垂,運行時才執(zhí)行相應的方法,這就是所謂的動態(tài)綁定火焰。
總結(jié)下@synthesize合成實例變量的規(guī)則劲装,有以下幾點:
1)如果指定了成員變量的名稱,會生成一個指定的名稱的成員變量,
2)如果這個成員已經(jīng)存在了就不再生成了.
3)如果是 @synthesize foo; 還會生成一個名稱為foo的成員變量,也就是說:如果沒有指定成員變量的名稱會自動生成一個屬性同名的成員變量昌简。
4)如果是 @synthesize foo = _foo; 就不會生成成員變量了.
假如property名為foo占业,存在一個名為_foo的實例變量,那么還會自動合成新變量么纯赎? 不會谦疾。
我們要搞清楚一個問題,什么情況下不會autosynthesis(自動合成)犬金?
同時重寫了setter和getter時
重寫了只讀屬性的getter時
使用了@dynamic時
在 @protocol 中定義的所有屬性
在 category 中定義的所有屬性
重載的屬性
當你在子類中重載了父類中的屬性餐蔬,你必須 使用@synthesize來手動合成ivar。
除了后三條佑附,對其他幾個我們可以總結(jié)出一個規(guī)律:當你想手動管理@property的所有內(nèi)容時樊诺,你就會嘗試通過實現(xiàn)@property的所有“存取方法”(the accessor methods)或者使用@dynamic來達到這個目的,這時編譯器就會認為你打算手動管理@property音同,于是編譯器就禁用了autosynthesis(自動合成)词爬。
因為有了autosynthesis(自動合成),大部分開發(fā)者已經(jīng)習慣不去手動定義ivar权均,而是依賴于autosynthesis(自動合成)顿膨,但是一旦你需要使用ivar锅锨,而autosynthesis(自動合成)又失效了,如果不去手動定義ivar恋沃,那么你就得借助@synthesize來手動合成ivar必搞。
其實,@synthesize語法還有一個應用場景囊咏,但是不太建議大家使用:
可以在類的實現(xiàn)代碼里通過@synthesize語法來指定實例變量的名字:
@implementation?CYLPerson
@synthesize?firstName?=?_myFirstName;
@synthesize?lastName?=?_myLastName;
@end
上述語法會將生成的實例變量命名為_myFirstName與_myLastName恕洲,而不再使用默認的名字。一般情況下無須修改默認的實例變量名梅割,但是如果你不喜歡以下劃線來命名實例變量霜第,那么可以用這個辦法將其改為自己想要的名字。筆者還是推薦使用默認的命名案户辞,因為如果所有人都堅持這套方案泌类,那么寫出來的代碼大家都能看得懂。