- 如果我假如写一个类,声明一个属性,比如:age(其中是int类型),他默认生成的是:set方法、get方法已经他们各自的实现,还有一个成员变量{ int _age;},代码如下:
#import <Foundation/Foundation.h>
@interface DGPerson : NSObject
{
int _age;
}
@property (assign, nonatomic) int age;
@end
.m文件
#import "DGPerson.h"
@implementation DGPerson
-(void)setAge:(int)age{
_age = age;
}
-(int)age{
return _age;
}
@end
- 三种方法实现给category 增加属性,
1.代码如下:
static const char DGNameKey;
- (void)setName:(NSString *)name{
objc_setAssociatedObject(self, &DGNameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self, &DGNameKey);
}
解释:这种办法是利用运行时给添加成员属性,其中他的key要求传递的是一个地址值 他是 const void * 类型,这种算是一种办法,但是不简便。
2.第二种方法。
#define DGNameKey @"asdasdas"
#pragma mark - 第二种办法
- (void)setName:(NSString *)name{
objc_setAssociatedObject(self, DGNameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self, DGNameKey);
}
3.第三种办法。
#pragma mark - 第三种办法
- (void)setName:(NSString *)name{
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self, _cmd);
}
解释:这种办法是最好的,因为他要求传递的是一个地址值,这个@selector(name)本质是一个地址,其中_cmd 在方法中执行相当于@selector( 方法);
-
底层原理:
其中他有四部分组成,一个是AssociationsManager、AssociationsHashMap、ObjectAssociationMap、ObjectAssociation组成,他们的关系是:
image.png
大致的思路是:他有一个管理者,管理所有的数据。其中一个AssociationsHashMap相当于一个字典,字典中的value 存储的是ObjectAssociationMap(他也相当于是一个字典),在这个字典中对value 和policy进行设置,其中AssociationsHashMap的key是:经过函数转换的对象。( disguised_ptr_t disguised_object = DISGUISE(object);)
网友评论