分類中是可以為一個類添加屬性的鹦蠕,但是一定做不到添加成員變量误阻,不要混淆了成員變量和屬性的概念.只是說現(xiàn)在Xcode自動會給屬性生成成員變量讓大家對這個概念有點(diǎn)混淆阻荒。Property是Property崔涂,Ivar是Ivar罗珍。分類里面不能添加Ivar是因?yàn)榉诸惐旧聿⒉皇且粋€真正的類,它并沒有自己的ISA .借用一位博主的話: "類最開始生成了很多基本屬性鹏往,比如IvarList淡诗,MethodList,分類只會將自己的method attach到主類,并不會影響到主類的IvarList韩容。這就是為什么分類里面不能增加成員變量的原因"
iOS分類中不能只是通過@property添加屬性款违。這里探討一下不能添加的原因和添加的方法
首先,創(chuàng)建一個person類群凶,代碼如下:
XGPerson.h
#import@interfaceXGPerson:NSObject/// 年齡@property(nonatomic,copy)NSString*age;/// 性別@property(nonatomic,copy)NSString*sex;- (void)text1;@end
XGPerson.m
#import"XGPerson.h"@implementationXGPerson- (void)text1 {NSLog(@"%s",__func__);}- (void)text2 {NSLog(@"%s",__func__);}@end
在控制器里獲取并打印該類的成員變量插爹、屬性和方法,代碼如下:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event {// 獲取成員變量unsignedintivarCount =0;? ? Ivar *ivars = class_copyIvarList([XGPersonclass], &ivarCount);for(inti =0; i < ivarCount; i++) {? ? ? ? Ivar ivar = ivars[i];NSLog(@"第%d個成員變量:%s",i,ivar_getName(ivar));? ? }? ? free(ivars);// 獲取屬性unsignedintpropertyCount =0;? ? objc_property_t *propertyList = class_copyPropertyList([XGPersonclass], &propertyCount);for(inti =0; i < propertyCount; i++) {? ? ? ? objc_property_t property = propertyList[i];NSLog(@"第%d個屬性:%s",i,property_getName(property));? ? }// 獲取方法列表unsignedintmethodCount =0;? ? Method *methods = class_copyMethodList([XGPersonclass], &methodCount);for(inti =0; i < methodCount; i++) {? ? ? ? Method method = methods[i];NSLog(@"第%d個方法:%s",i, sel_getName(method_getName(method)));? ? }}
此時控制臺輸出如下:
沒有分類時.png
這里需要提出的是请梢,平時使用@property的時候赠尾,系統(tǒng)會自動生成帶“_”的成員變量和該變量的setter和getter方法。也就是說毅弧,屬性相當(dāng)于一個成員變量加getter和setter方法气嫁。那么,在分類里使用@property會是什么樣子呢够坐,下面來創(chuàng)建一個分類:
XGPerson+height.h
#import"XGPerson.h"@interfaceXGPerson(height)@property(nonatomic,copy)NSString*height;@end
XGPerson+height.m
#import"XGPerson+height.h"#import@implementationXGPerson(height)@end
如果像上面一樣只在.h文件里聲明height寸宵,那么.m文件里會出現(xiàn)兩個警告,意思是說沒有實(shí)現(xiàn)setter和getter方法元咙。
警告.png
此時在控制器里執(zhí)行touchesBegan方法邓馒,控制臺輸出如下:
有分類未實(shí)現(xiàn)存取方法.png
可以看到,此時person類里并沒有添加帶“_”的成員變量蛾坯,也沒有實(shí)現(xiàn)setter和getter方法,只是在屬性列表里添加了height屬性疏遏。并且此時如果在控制器里調(diào)用self.height脉课,程序運(yùn)行時會報(bào)錯,顯示找不到該方法财异。實(shí)現(xiàn)一下person分類里的兩個方法:
XGPerson+height.m
#import"XGPerson+height.h"#import@implementationXGPerson(height)- (NSString*)height { } - (void)setHeight:(NSString*)height { }@end
此時在控制器里執(zhí)行touchesBegan方法倘零,控制臺輸出如下:
有分類實(shí)現(xiàn)存取方法.png
可以看到即使實(shí)現(xiàn)了setter和getter方法,也仍然沒有添加帶“”的成員變量戳寸,也就是說呈驶,在setter和getter方法里仍然不能直接訪問以下劃線開頭的成員變量,因?yàn)樵诜诸惱镉聾property聲明屬性時系統(tǒng)并沒有添加以“”開頭的成員變量疫鹊。此時要達(dá)到添加的目的可以使用運(yùn)行時的關(guān)聯(lián)對象袖瞻。示例代碼如下:
XGPerson+height.m
#import"XGPerson+height.h"#import@implementationXGPerson(height)- (NSString*)height {returnobjc_getAssociatedObject(self,@"height"); } - (void)setHeight:(NSString*)height { objc_setAssociatedObject(self,@"height", height, OBJC_ASSOCIATION_COPY_NONATOMIC); }@end
當(dāng)然也可以在setter和getter方法里訪問該類其他的屬性,比如在UIView的分類的里添加x拆吆、y屬性聋迎,可以直接返回self.frame.origin.x和self.frame.origin.y。
總結(jié)
在分類里使用@property聲明屬性枣耀,只是將該屬性添加到該類的屬性列表霉晕,并聲明了setter和getter方法,但是沒有生成相應(yīng)的成員變量,也沒有實(shí)現(xiàn)setter和getter方法牺堰。所以說分類不能添加屬性拄轻。但是在分類里使用@property聲明屬性后,又實(shí)現(xiàn)了setter和getter方法伟葫,那么在這個類以外可以正常通過點(diǎn)語法給該屬性賦值和取值恨搓。就是說,在分類里使用@property聲明屬性扒俯,又實(shí)現(xiàn)了setter和getter方法后奶卓,可以認(rèn)為給這個類添加上了屬性。