一般的我们会用到继承父类类给一个父类添加属性,但是在某些特性的情况下(例如:团队开发中,解决相同类的冲突的时候会用到分类)需要给一个类的分类添加属性。而我们知道,分类是没有父类的,也就是说,在分类添加属性的时候,只会定义set和get方法,但是不会实际的成员变量和方法实现。例如:
@interface Dog (My) @property(nonatomic,copy)NSString * name; @end @implementation Dog (My) @end
int main(int argc, const char * argv[]) { @autoreleasepool { Dog * dog1 = [[Dog alloc]init]; dog1.name = @"dog1"; Dog * dog2 = [[Dog alloc]init];
dog2.name = @"dog2"; NSLog(@"dog1==%@,dog2==%@",dog1.name,dog2.name); } return 0; } //程序运行到dog1.name = @"dog1"处就会奔溃。
此时我们如果想自己给这个分类写一个set和get方法的实现。也会出现问题。例如:
@implementation Dog (My) NSString * _name; - (void)setName:(NSString *)name{ _name = name; } - (NSString *)name{ return _name; } @end //再次运行main函数,程序结果会打印:dog1==dog2,dog2==dog2。 //这个与实际dog1.name不符,出现bug
此时,用Rumetime的方法就能实现我们的目的。核心思想就是把一个类和一个属性值产生关联。
#import "Dog+My.h" #import <objc/runtime.h> @implementation Dog (My) - (void)setName:(NSString *)name{ /* id object : 执行对象 const void *key : 属性名 id value : 属性值 objc_AssociationPolicy policy :copy,nonatomica等属性 */ objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_COPY_NONATOMIC); } - (NSString *)name{ return objc_getAssociatedObject(self, @"name"); } @end
//打印结果dog1==dog1,dog2==dog2。完成所需目的