运行时一看就是很牛逼的大牛使用的,我是小菜,只是来学习一下,分析一下使用方法,主要讲到
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
如果我们需要动态的加载一个属性,我们就要使用这个set方法
首先我们分析一下,参数含义
- id object : 源对象 -指定我们需要绑定的对象,e.g ,给一个字符串添加一个内容
- const void * key : 设置一个静态常亮,也就是Key 值,通过这个我们可以找到我们关联对象的那个数据值
- id value 这个是我们打点调用属性的时候会自动调用set方法进行传值
- objc_AssociationPolicy policy : 这个是关联策略,这几个管理策略,我们看下都有什么,
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
// 第一个关联策略是基于基本类型的,也就是我们常用的assign 属性
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
//关联策略是基于对象类型的,如我们正常的是retain nonatomic (非原子操作)类型 ,retain : 保留一个引用指针,内存地址不修改,指向同一块内存地址
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
//这个相当于属性中对一些对象或者字符串进行的copy 这个是拷贝一个新对象,内存地址不在一起,还是使用的非原子类型,非原子类型我们也称之为线程不安全的操作,但是对于OC里面的数据操作,我们尽量避开原子操作,原子操作是线程安全的,会影响我们对数据的写入操作
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
* The association is not made atomically. */
// 简单的指针引用, retain 操作
OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
* The association is made atomically. */
//把简单的对象拷贝到一个新的内存地址
OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
* The association is made atomically. */
};
以上就是我们动态添加属性索要用到的一些方法,简单理解就是
: set(源对象,常亮key,数值,属性关联策略)
下面这个想必都可以看明白,类似我们的getter 方法
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
同样 传入的参数有两个:
- id object :当前的属性是关联在那个对象上的,和set 保持一致
- const void * key : 静态关键key 要获取的值就是根据关联对象可以关键key 获取对应的数据
使用方法我们介绍完毕了,下面直接代码
UIControl+RYButton.h 文件
#import <UIKit/UIKit.h>
@interface UIControl (RYButton)
// 声明一个时间间隔
@property (assign,nonatomic)NSTimeInterval ry_time;
@end
UIControl+RYButton.m 文件
#import "UIControl+RYButton.h"
#import <objc/runtime.h>
static const char * RY_CLICKKEY = "ry_clickkey";
@implementation UIControl (RYButton)
- (void)setRy_time:(NSTimeInterval)ry_time{
objc_setAssociatedObject(self, RY_CLICKKEY, @(ry_time), OBJC_ASSOCIATION_ASSIGN);
}
- (NSTimeInterval)ry_time{
return [objc_getAssociatedObject(self, RY_CLICKKEY) doubleValue];
}
@end
使用方法
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ThirdPartService * service = [ThirdPartService new];
NSLog(@"%@ ---%@",NSStringFromSelector(_cmd),service);
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.ry_time = 1.0f;
}
这个就是动态添加属性的简单使用,如果有错误地方,欢迎留言指正,加群备注:(iOS 简书 ) 技术学习交流
网友评论
这个参数 为嘛要 static const char * RY_CLICKKEY = "ry_clickkey"; 这么写
我发现不加static也可以
或者我直接这么写也发现能行
- (void)setLd_Title:(NSString *)ld_Title
{
objc_setAssociatedObject(self, @"哈哈", ld_Title, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString*)ld_Title
{
return objc_getAssociatedObject(self, @"哈哈");
}
而且static修饰的变量 是在当前类释放后 而该变量保存的值并不变
static const char * RY_CLICKKEY = "ry_clickkey";这么写 我觉得不靠谱啊
static char * const RY_CLICKKEY = "ry_clickkey";这么写 应该是靠谱的
属性方法被添加到对象当中之后, 这个属性存储在什么位置? 也是存在方法列表吗?
如果我存储了一个值, 这个值存储在什么位置?