iOS分類:
很多說法是只能添加方法,而不能添加成員變量或屬性。
有些人可能知道,這種說法是不嚴謹的,並不是絕對不能添加變量。
解釋如下:
我們知道在一個類中用@property聲明屬性,編譯器會自動幫我們生成_成員變量和setter/getter,但分類的指針結構體中,根本沒有屬性列表。所以在分類中用@property聲明屬性,既無法生成_成員變量也無法生成setter/getter。
因此結論是:我們可以用@property聲明屬性,編譯會通過,但run之后就會崩潰。
問題來了。。
既然報錯的根本原因是使用了系統沒有生成的setter/getter方法,可不可以在手動添加setter/getter來避免崩潰,完成調用呢?
其實是可以的。由於OC是動態語言,方法真正的實現是通過runtime完成的,雖然系統不給我們生成setter/getter,但我們可以通過runtime手動添加setter/getter方法。那具體怎么實現呢?
舉例如下:
分類.h
#import "Programmer.h" @interface Programmer (Category) @property(nonatomic,copy) NSString *nameWithSetterGetter; //設置setter/getter方法的屬性 - (void) programCategoryMethod; //分類方法 @end
分類.m
#import "Programmer+Category.h" #import <objc/runtime.h> static NSString *nameWithSetterGetterKey = @"nameWithSetterGetterKey"; @implementation Programmer (Category)
- (void)setNameWithSetterGetter:(NSString *)nameWithSetterGetter { objc_setAssociatedObject(self, &nameWithSetterGetterKey, nameWithSetterGetter, OBJC_ASSOCIATION_COPY); } - (NSString *)nameWithSetterGetter { return objc_getAssociatedObject(self, &nameWithSetterGetterKey); } - (void)programCategoryMethod { NSLog(@"實現分類方法"); } @end
重點就是兩個runtime實現方法,如果不寫這個,只要你申明了屬性,運行肯定會報錯;如果加了這兩個方法,就能運行通過了,而且,我們在其他地方也能正常使用了
Programmer *programmer = [[Programmer alloc]init]; //通過runtime實現了setter/getter programmer.nameWithSetterGetter = @"有setter/getter"; //調用setter,成功 NSLog(@"%@",programmer.nameWithSetterGetter); //調用getter,成功
