美文网首页IOS收藏iOS iOS开发
iOS runtime 运行时,动态添加属性方法

iOS runtime 运行时,动态添加属性方法

作者: Raybon_lee | 来源:发表于2015-12-12 16:05 被阅读8147次

运行时一看就是很牛逼的大牛使用的,我是小菜,只是来学习一下,分析一下使用方法,主要讲到

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 简书 ) 技术学习交流

相关文章

网友评论

  • LD_左岸:const void * key : 设置一个静态常量,也就是Key 值,通过这个我们可以找到我们关联对象的那个数据值
    这个参数 为嘛要 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";这么写 应该是靠谱的
    Raybon_lee:这个其实也要看实际场景的,我这里只是个例子,const char * 其实我本想是一个常量指针, 下面哪种是一个char 类型的 指针常量,const 修饰的类型, 不容易被修改内容,这是我选用的目的,static 我是想着存储一份静态的常量, 所以加上这个了,按照你说的类型释放,这个其实不是个类别,我想是尽量不释放,不会占用太多内存,对于指针可以向你学习一下,不常用,会用错,不足之处还望指正,互相交流
  • Mrshang110:objc_setAssociatedObject(self, RY_CLICKKEY, @(ry_time), OBJC_ASSOCIATION_ASSIGN);这里用OBJC_ASSOCIATION_ASSIGN有问题,应该使用OBJC_ASSOCIATION_RETAIN_NONATOMIC
    Raybon_lee:@yqy159 已调整
    Breezes:@Raybon_lee 这地方文章里改一下比较好
    Raybon_lee:@Mrshang110 谢谢指出
  • 7b15af9a092f:问您几个问题?
    属性方法被添加到对象当中之后, 这个属性存储在什么位置? 也是存在方法列表吗?
    如果我存储了一个值, 这个值存储在什么位置?
    Raybon_lee:@西夏ci 为什么要这么用呢
    9648f522204f:你好,那这个属性能储存在数组 和数据库吗
    Raybon_lee:@mg夏雨 对象的临时内存
  • zeroskylian:请问po主,用runtime添加属性有什么好处呢
    Raybon_lee:@李连毛 是的,分类不能添加属性,是动态添加的
    健了个平_24:@zeroskylian 可以为一个类添加属性,不用自定义子类
    李连毛:@zeroskylian 分类应该不能添加属性吧,只能通过runtime添加吧。
  • 梁伟杰:为什么你在类别文件中可以声明属性的呢??不是说在类别中只可以定义方法而不可以定义属性吗?
    Raybon_lee:@梁伟杰 可以使用runtime添加属性
  • d3e5f7545449:限制button不能重复点击时 加入你上面的那些代码没有用啊
    Raybon_lee:@零零妖 可能代码没写好
  • 诸子百家谁的天下:6666666666666,好多第三方都是这样动态添加属性的!
    Raybon_lee:@诸子百家谁的天下 :smile: 用着好用就行,不乱用就不会有事,满足项目需求
  • 曲年:如果我现在需要为所有的UIControl 添加一个属性block。并且这个block处理点击事件。怎么才能实现呢?
    Raybon_lee:@曲年 和正常一样添加block属性,在你需要调用的地方调用

本文标题:iOS runtime 运行时,动态添加属性方法

本文链接:https://www.haomeiwen.com/subject/lfgyhttx.html