美文网首页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添加属性
      • 零零妖:限制button不能重复点击时 加入你上面的那些代码没有用啊
        Raybon_lee:@零零妖 可能代码没写好
      • 诸子百家谁的天下:6666666666666,好多第三方都是这样动态添加属性的!
        Raybon_lee:@诸子百家谁的天下 :smile: 用着好用就行,不乱用就不会有事,满足项目需求
      • 曲年:如果我现在需要为所有的UIControl 添加一个属性block。并且这个block处理点击事件。怎么才能实现呢?
        Raybon_lee:@曲年 和正常一样添加block属性,在你需要调用的地方调用

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

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