在分类中使用属性block
通过分类我们可以为iOS UIKit 的常用控件添加方法,如果想添加属性怎么办呢,如果我们采用常规的方法定义属性,XCode会提示一下错误:
解决这个问题可以通过OC的runtime。
如果不写@dynamic block;
就会报上面的错误。
@dynamic 就是要告诉编译器,代码中用@dynamic修饰的属性,其getter和setter方法会在程序运行的时候或者用其他方式动态绑定,以便让编译器通过编译。这个跟@synthesize自动合成属性的getter/setter方法原理是不一样的。
#import <UIKit/UIKit.h>
typedef void(^doneBlock)();
@interface UIToolbar (STBar)
/**
* 点击完成按钮的回调
*/
@property (nonatomic,copy) doneBlock block;
/**
* 创建带完成按钮的方法
*/
- (void)createDoneButtonBar;
@end
对应的实现文件中对block属性通过objc_getAssociatedObject和objc_setAssociatedObject方法进行绑定。
#import "UIToolbar+STBar.h"
#import <objc/runtime.h>
static const void *UtilityKey = &UtilityKey;
@implementation UIToolbar (STBar)
@dynamic block;
- (doneBlock)block {
return objc_getAssociatedObject(self, UtilityKey);
}
- (void)setBlock:(doneBlock)block{
objc_setAssociatedObject(self, UtilityKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)createDoneButtonBar {
UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStyleDone target:self action:@selector(doneAction:)];
UIBarButtonItem *space=[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:nil];
[space setWidth:250];
[self setItems:@[space,done]];
}
- (void)doneAction:(UIButton *)button {
if (self.block){
self.block();
}else{
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
}
}