为什么分类不能添加属性
CategoryCategory 是表示一个指向分类的结构体的指针,其定义如下:typedef struct objc_category *Category;struct objc_category { char *category_name OBJC2_UNAVAILABLE; // 分类名 char *class_name OBJC2_UNAVAILABLE; // 分类所属的类名 struct objc_method_list *instance_methods OBJC2_UNAVAILABLE; // 实例方法列表 struct objc_method_list *class_methods OBJC2_UNAVAILABLE; // 类方法列表 struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 分类所实现的协议列表}复制代码
结构体没有属性列表:
这也就是为什么分类不能添加属性的本质原因。
属性是什么
属性 = 成员变量 + set方法 + get方法。复制代码
@interface DKObject : NSObject@property (nonatomic, strong) NSString *property;@end复制代码
@implementation DKObject { NSString *_property;}- (NSString *)property { return _property;}- (void)setProperty:(NSString *)property { _property = property;}@end复制代码
- 生成实例变量 _property
- 生成 getter 方法 - property
- 生成 setter 方法 - setProperty:
当我们声明一个属性str的时候,在编译阶段,编译器会自动给对象添加一个实例变量_str和它的存取方法- (void)setStr:(NSString *)str和- (NSString *)str。这个过程由于是在编译阶段自动合成的,所以我们在编辑阶段是看不到的。
怎么添加属性
由于OC是动态语言,可以通过runtime手动添加setter/getter方法。
#importstatic NSString *nameWithSetterGetterKey = @"nameWithSetterGetterKey"; //定义一个key值@implementation Programmer (Category)//运行时实现setter方法- (void)setNameWithSetterGetter:(NSString *)nameWithSetterGetter { objc_setAssociatedObject(self, &nameWithSetterGetterKey, nameWithSetterGetter, OBJC_ASSOCIATION_COPY);}//运行时实现getter方法- (NSString *)nameWithSetterGetter { return objc_getAssociatedObject(self, &nameWithSetterGetterKey);}@end复制代码
关联对象associatedObject理解
- objc_setAssociatedObject
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);复制代码
以键值对形式添加关联对象复制代码
参数 | 含义 |
---|---|
id | 主对象 |
key | 键值对key(必须要唯一,所以用static修饰) |
value | 关联对象 |
policy | 存储策略:是枚举,定义了内存管理语义 |
- id objc_getAssociatedObject(id object, const void *key);
根据给定的键从某对象中获取相应的关联对象值复制代码
- void objc_removeAssociatedObjects(id object)
移除指定对象的关联对象复制代码
引用