對于category分類而言赂苗,一般我們不給分類添加屬性蝎亚,只給它添加方法蚕甥。這是因為給分類添加完屬性之后舌镶,在其他類中不能正常地使用點語法來給這個分類里面的屬性賦值和取值糊啡,所以添加了也沒有什么意義拄查。本篇文章就要介紹如何使用Runtime運行時機制中的關(guān)聯(lián)對象方式來給分類添加屬性,使之能夠在其他類中正常地使用點語法來賦值和取值棚蓄。
在探究關(guān)聯(lián)對象的方式之前堕扶,我們需要明確一點:
可以給分類添加屬性,但是不能添加成員變量梭依。給分類添加成員變量的話稍算,程序在編譯的時候會報錯:
然后還要明確的是在普通類中添加一個屬性,系統(tǒng)在編譯的時候會自動為我們做三件事:
- 會在.h文件中生成一個帶下橫線的成員變量役拴;
- 會在.h文件中生成這個屬性的set和get方法的聲明糊探;
- 會在.m文件中生成這個屬性的set和get方法的實現(xiàn)。
但是給分類添加一個屬性,系統(tǒng)在編譯的時候只會為我們做一件事:
會在.h文件中生成這個屬性的set和get方法的聲明科平。
因為系統(tǒng)不能自動生成新添加屬性的set和get方法的實現(xiàn)褥紫,所以想要在其他類中能夠使用這個屬性的點語法來給這個屬性賦值和取值的話就要用Runtime運行時機制的關(guān)聯(lián)對象的方式在這個分類的.m文件中實現(xiàn)set和get方法。
使用關(guān)聯(lián)對象方式的步驟:
1. 在分類的.h文件中添加新的屬性:
#import "ZPPerson.h"
NS_ASSUME_NONNULL_BEGIN
@interface ZPPerson (ZPTest)
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int weight;
@end
NS_ASSUME_NONNULL_END
2. 在分類的.m文件中撰寫這個屬性的set和get方法:
#import "ZPPerson+ZPTest.h"
#import <objc/runtime.h>
@implementation ZPPerson (ZPTest)
//是一個指針瞪慧,里面可以存儲地址值髓考。
static const void *nameKey = &nameKey;
static const void *weightKey = &weightKey;
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self, nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name
{
return objc_getAssociatedObject(self, nameKey);
}
- (void)setWeight:(int)weight
{
objc_setAssociatedObject(self, weightKey, [NSNumber numberWithInt:weight], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (int)weight
{
return [objc_getAssociatedObject(self, weightKey) intValue];
}
@end
然后在其他類中就可以使用點語法來訪問這個分類里面的屬性了。所以關(guān)聯(lián)對象的方式是Runtime運行時機制的又一重大應(yīng)用汞贸。
應(yīng)當注意的是绳军,當使用關(guān)聯(lián)對象的方式給分類添加屬性之后,在程序編譯結(jié)束的時候矢腻,會產(chǎn)生這個屬性的set门驾、get方法的聲明以及set、get方法的實現(xiàn)多柑,并且會把這些東西存放在 struct _category_t 結(jié)構(gòu)體(分類的底層實現(xiàn))中奶是,但還是不會產(chǎn)生帶下橫線的成員變量。
”三人行竣灌,必有我?guī)熝伞埃?歡迎各位批評指正聂沙。
如果您還覺得我寫的不錯的話請您點贊加關(guān)注,您的肯定是我前進的最大動力初嘹!
我是愛學(xué)習(xí)也愛您的樹懶O(∩_∩)O