类中使用@property
@property (nonatomic,strong) NSString * name;
上面代码做了三件事
1.生成成员变量_name
2.生成setter,getter声明
3.生成setter,getter实现
分类Category中使用@property
只会生成setter,getter声明.不会做其他两件事.
不能在Category中直接添加成员变量.
image.png
Category中添加成员变量
@interface LDPerson (Test)
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) int weight;
@end
#import <objc/runtime.h>
@implementation LDPerson (Test)
- (void)setName:(NSString *)name
{
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name
{
// 隐式参数
// _cmd == @selector(name)
return objc_getAssociatedObject(self, _cmd);
}
- (void)setWeight:(int)weight
{
objc_setAssociatedObject(self, @selector(weight), @(weight), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (int)weight
{
// _cmd == @selector(weight)
return [objc_getAssociatedObject(self, _cmd) intValue];
}
字符串常量(字面量写法@"name")存放在常量区,多个字符串常量的地址是相同的.
实现关联对象技术的核心对象
- AssociationsManager
- AssociationsHashMap
- ObjectAssociationMap
- ObjcAssociation
objc4源码解读:objc-references.mm
class AssociationsManager {
// associative references: object pointer -> PtrPtrHashMap.
static AssociationsHashMap *_map;//主要对象
public:
AssociationsManager() { AssociationsManagerLock.lock(); }
~AssociationsManager() { AssociationsManagerLock.unlock(); }
AssociationsHashMap &associations() {
if (_map == NULL)
_map = new AssociationsHashMap();
return *_map;
}
};
class AssociationsHashMap : public unordered_map<disguised_ptr_t, ObjectAssociationMap *, DisguisedPointerHash, DisguisedPointerEqual, AssociationsHashMapAllocator>
class ObjectAssociationMap : public std::map<void *, ObjcAssociation, ObjectPointerLess, ObjectAssociationMapAllocator>
class ObjcAssociation {
uintptr_t _policy;//主要对象
id _value;//主要对象
public:
ObjcAssociation(uintptr_t policy, id value) : _policy(policy), _value(value) {}
ObjcAssociation() : _policy(0), _value(nil) {}
uintptr_t policy() const { return _policy; }
id value() const { return _value; }
bool hasValue() { return _value != nil; }
};
实现关联对象的核心代码:
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
参数解释:
给self对象添加关联属性name.隐私策略为OBJC_ASSOCIATION_COPY_NONATOMIC,key为@selector(name)即getter
由源码可知:
实现关联对象的核心对象是AssociationsManager,该AssociationsManager内部有一个成员变量AssociationsHashMap
AssociationsHashMap是一个字典数据结构,Key为disguised_ptr_t,key是通过函数DISGUISE(object)获取, object == self.value为ObjectAssociationMap.此ObjectAssociationMap中存储着ObjectAssociationMap,ObjectAssociationMap也是一个字典结构,key为我们在API中传入的key即为@selector(name).value为ObjectAssociation.在ObjectAssociation中存储这policy和value
设置关联对象核心API:
void objc_setAssociatedObject(id object,const void * key,id value,objc_AssociationPolicy policy)
- 关联对象并不是存储在被关联对象本身内存中
- 关联对象存储在全局统一的一个`AssociationsManager中
- 设置关联对象为
nil就相当于移除关联对象,即属性name的位置传入nil
关联对象相关API:
添加关联对象:void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy)
获得关联对象:id objc_getAssociatedObject(id object, const void * key)
移除所有的关联对象:void objc_removeAssociatedObjects(id object)
objc_AssociationPolicy
| objc_AssociationPolicy | 对应的修饰符 |
|---|---|
| OBJC_ASSOCIATION_ASSIGN | assign |
| OBJC_ASSOCIATION_RETAIN_NONATOMIC | strong, nonatomic |
| OBJC_ASSOCIATION_COPY_NONATOMIC | copy, nonatomic |
| OBJC_ASSOCIATION_RETAIN | strong, atomic |
| OBJC_ASSOCIATION_COPY | copy, atomic |














网友评论