runtime之objc_setAssociatedObject

在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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,219评论 30 472
  • 1.runtime体验 1.1.引言 运行时作为面试题中高阶问题必不可少的一个技能点。经常面试官会问道是否使...
    2897275c8a00阅读 986评论 0 5
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,026评论 19 139
  • 1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch...
    阳光的大男孩儿阅读 5,047评论 0 13
  • 吃完早饭,妻子说去趟西单商场买件衣服,好参加战友聚会。想不到本来不大喜欢买衣服的她,把下个月去舟山群岛的...
    杨合林阅读 341评论 2 0