类中使用@property
@property (nonatomic,strong) NSString * name;
上面代码做了三件事
1.生成成员变量_name
2.生成setter
,getter
声明
3.生成setter
,getter
实现
分类Category中使用@property
只会生成setter
,getter
声明.不会做其他两件事.
不能在Category中直接添加成员变量.
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 |