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