iOS使用Runtime给分类动态绑定属性

在runtime时,动态的给对象增加键值或属性(或者形象的比喻为给对象Object插上本没有的大翅膀,让Object的能力更强大),通过#import<objc/runtime.h>,调用下面的两个函数即可以实现:

objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);

id objc_getAssociatedObject(id object, const void *key);

先看给对象动态的绑定其它对象或值的例子:

static NSString * const key = @"Button_Key";
static NSString * const labelKey = @"Label_Key";

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(30, 30, 80, 40)];
    [button setTitle:@"测试" forState:UIControlStateNormal];
    [button setTitleColor:UIColorMake(30, 30, 100) forState:UIControlStateNormal];
    [button addTarget:self action:@selector(clickEvent:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(30, 80, 140, 40)];
    label.text = @"label_text";
    [self.view addSubview:label];
    
    objc_setAssociatedObject(button, &key, @"nice_button", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    objc_setAssociatedObject(button, &labelKey, label, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)clickEvent:(id)sender {
    UIButton *tempButton = sender;
    NSString *string = objc_getAssociatedObject(tempButton, &key);
    NSLog(@"%@", string);
    
    UILabel *tempLabel = objc_getAssociatedObject(tempButton, &labelKey);
    tempLabel.text = string;
}

例子的效果是:点击按钮后,label的文字变成了nice_button。

上面就是通过设置了两个Key值,分别绑定了string和label对象到button上,在点击事件中通过键Key取出了对应的string和label。

常见的应用还有给类增加额外的属性,这里需要分类category与runtime绑定的配合,大概代码如下:

//ViewController+Objc.h文件

#import "ViewController.h"

@interface ViewController (Objc)
@property (nonatomic, retain) NSString *themeText;  //主题内容
@end

----------------------------------

//ViewController+Objc.m文件

#import "ViewController+Objc.h"
#import <objc/runtime.h>

static NSString * const themeKey = @"theme_key";

@implementation ViewController (Objc)

- (NSString *)themeText {
    return (NSString *)objc_getAssociatedObject(self, &themeKey);
}

- (void)setThemeText:(NSString *)themeText {
    objc_setAssociatedObject(self, &themeKey, themeText, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

这样就给ViewController增加了一个themeText的string属性。然后就可以在代码里,愉快的调用self.themeText了。

开始我觉得ViewController+Objc.h文件里,已经写了themeText了,当然可以调用了,完全不需要runtime的绑定代码。其实试了下,语法可以通过,但是运行会nil异常报错。

但是如果为了更好的理解动态的增加属性,可以把ViewController+Objc.h文件写成这样:

#import "ViewController.h"

@interface ViewController (Objc)
- (NSString *)themeText;
- (void)setThemeText:(NSString *)themeText;
@end

程序依旧可以运行。这样看起来,就可以更好的理解给类动态的绑定增加属性了。

posted @ 2018-07-12 16:08  Mr轨迹  阅读(288)  评论(0编辑  收藏  举报