美文网首页
runtime之objc_setAssociatedObject

runtime之objc_setAssociatedObject

作者: 辰牧殇 | 来源:发表于2017-02-08 15:50 被阅读30次

    在objectiv-c中,如果我们想在不修改源码的基础上给一个类增加方法,可以使用类别(category),但是如果想增加属性呢?查找资料了解到,通过objective-c的运行时特性可以实现给类动态的添加属性。

    需要用到的两个runtime方法:

    /** 
    * Sets an associated value for a given object using a given key and association policy.
    * 
    * @param object The source object for the association.
    * @param key The key for the association.
    * @param value The value to associate with the key key for object. Pass nil to clear an existing association.
    * @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
    */
    OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    
    /** 
     * Returns the value associated with a given object for a given key.
     * 
     * @param object The source object for the association.
     * @param key The key for the association.
     */
    OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
    

    翻译过来就是:

    /** 
    * 将一个值(value)通过关键字(key)和关联策略(policy)与给定的对象(object)关联起来
    * 
    * @param object 源对象
    * @param key 进行关联的关键字
    * @param value 关联的值
    * @param policy 关联策略
    */
    OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    
    /** 
     * 通过关键字(key)获取到对象关联的值(value)
     * 
     * @param object 源对象
     * @param key 进行关联的关键字
     */
    OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
    

    关键字是一个void类型的指针,每一个关联的关键字必须是唯一的,通常都是会采用静态变量来作为关键字。

    关联策略:这里的关联策略和声明属性时使用的关键字类似

    typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
        OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */
        OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. 
                                                *   The association is not made atomically. */
        OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied. 
                                                *   The association is not made atomically. */
        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. */
    };
    

    举个例子

    .h文件

    #import <UIKit/UIKit.h>
    
    @interface UIButton (test)
    @property (nonatomic) UIColor * defaultColor;
    @end
    

    .m文件

    #import "UIButton+test.h"
    #import <objc/runtime.h>
    
    static const char defaultColorKey;
    
    @implementation UIButton (test)
    
    @dynamic defaultColor;
    
    - (void)setDefaultColor:(UIColor *)defaultColor {
        //进行绑定,把 defaultColor 和 btn 绑定起来,将来就可以通过 btn 获得 defaultColor 了
        objc_setAssociatedObject(self, &defaultColorKey, defaultColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (UIColor *)defaultColor {
        //通过self 和 关键字 获得绑定的 defaultColor
        return objc_getAssociatedObject(self, &defaultColorKey);
    }
    
    @end
    

    viewController

    #import "ViewController.h"
    #import "UIButton+test.h"
    
    @interface ViewController ()
    @property (nonatomic) UIButton * btn;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self.view addSubview:self.btn];
        self.btn.center = self.view.center;
    }
    
    - (UIButton *)btn {
        if (_btn == nil) {
            _btn = [UIButton buttonWithType:UIButtonTypeSystem];
            _btn.defaultColor = [UIColor redColor];
            _btn.backgroundColor = [UIColor orangeColor];
            _btn.frame = CGRectMake(0, 0, 240, 60);
            [_btn setTitle:@"点我试试" forState:UIControlStateNormal];
            [_btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
            [_btn addTarget:self action:@selector(btnDidClicked:) forControlEvents:UIControlEventTouchUpInside];
        }
        return _btn;
    }
    - (void)btnDidClicked:(UIButton *)btn {
        _btn.backgroundColor = btn.defaultColor;
    }

    相关文章

      网友评论

          本文标题:runtime之objc_setAssociatedObject

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