UIBarButtonItem的原生的初始化方法只有使用Target Action来绑定事件响应,大部分时候都没问题,但是偶尔有需求如果能用block来处理它的事件响应就更方便了,看过网上一些人会对UIBarButtonItem或者UIButton添加一个父类来做封装,个人觉得不太友好,以后每次使用都要记得用那个新的类。这里给出一个个人觉得比较方便,代码也比较少的写法,就是使用Category分类来给原生的UIBarButtonItem进行扩展。
主要就用到两个点的知识,一个是Category,一个是runtime
其中runtime主要也就用到两个很常用的方法
动态给对象绑定属性:objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy)
获取对象的绑定属性objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
我们主要用以上两个方法来存取block就行了,如果对runtime不了解的可以去搜一搜,别人写的太多了,这里就不做介绍。
然后创建UIBarButtonItem的分类UIBarButtonItem+Block.h和UIBarButtonItem+Block.m文件,代码如下:
UIBarButtonItem+Block.h
#import <UIKit/UIKit.h>
@interface UIBarButtonItem (Block)
//就用这个方法给对象添加一个block的响应
- (void)bindClickHandlerBlock:(dispatch_block_t)block;
@end
UIBarButtonItem+Block.m
#import "UIBarButtonItem+Block.h"
//引入runtime库
#import <objc/runtime.h>
@implementation UIBarButtonItem (Block)
//用于动态绑定对象的key
static char targetClosureKey;
#pragma mark - public
- (void)bindClickHandlerBlock:(dispatch_block_t)block
{
//绑定block之前先将可能在初始化时候添加的target action替换成我们自己的
//这样这个按钮点击的时候就会触发我们这个分类里的activeAction方法
self.target = self;
self.action = @selector(activeAction);
//将传入的block对象跟我们的key绑定起来(可以理解为将block存入这个对象的叫做targetClosureKey的属性里
//最后那个参数OBJC_ASSOCIATION_COPY_NONATOMIC表示我们用copy的策略来赋值)
objc_setAssociatedObject(self, &targetClosureKey, block, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
#pragma mark - private
- (void)activeAction
{
//按钮点击了会触发此方法,我们就读取之前绑定的block对象
dispatch_block_t handler = objc_getAssociatedObject(self, &targetClosureKey);
//如果有就调用它
if (handler) {
handler();
}
}
@end
是不是很简单?下面就是看如何使用了
//在需要用的地方导入分类头文件
#import "UIBarButtonItem+Block.h"
//跟平常一样,以前你的UIBarButtonItem怎么初始化,现在还是怎么初始化,这就是使用Category比套一个父类优秀的地方了。
//系统的初始化方法里的target和action填nil就可以了,反正之后也会被我们的分类修改了。
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"image"] style:UIBarButtonItemStylePlain target:nil action:nil];
//对着这个新的 UIBarButtonItem对象调用我们上面写的分类方法,就能给他绑定点击响应block回调了。
[item bindClickHandlerBlock:^{
NSLog("click!!!");
}];
结语:
1.记得组合(category)要优于继承(添加父类)。
2.偶尔使用runtime可以简化代码,但是不能滥用,能力越大责任越大。
网友评论