今天在简书上看到一篇大神写的以block的形式自定义返回按钮动作的按钮,然后自己尝试了一些想法,以下是在借鉴了大神的文章后,自己想的三种方法来实现不调用按钮的addTarget方法改用block的形式降低代码的分散度。
方法一:通过继承UIButton自定义CustomButton
在 CustomButton.h
文件中的代码:
#import <UIKit/UIKit.h>
// 定义block
typedef void(^CompletionHandler)(void);
@interface CustomButton : UIButton
// 用此方法代替原有的addTarget方法
- (void)addActionForControlEvents:(UIControlEvents)controlEvents respond:(CompletionHandler)completion;
@end
在 CustomButton.m
文件中的代码:
#import "CustomButton.h"
@interface CustomButton()
@property (nonatomic, copy) CompletionHandler completion;
@end
@implementation CustomButton
- (void)addActionForControlEvents:(UIControlEvents)controlEvents respond:(CompletionHandler)completion {
[self addTarget:self action:@selector(didClickButton) forControlEvents:controlEvents];
self.completion = completion;
}
// 点击button时
- (void)didClickButton {
self.completion();
}
@end
方法二:通过分类的方式并使用运行时关联对象
在 UIButton+Category1.h
文件中的代码:
#import <UIKit/UIKit.h>
typedef void(^CompletionHandler)(void);
@interface UIButton (Category1)
@property (nonatomic, copy) CompletionHandler completion;
- (void)addActionForControlEvents:(UIControlEvents)controlEvents respond:(CompletionHandler)completion;
@end
在 UIButton+Category1.m
文件中的代码:
#import "UIButton+Category1.h"
#import <objc/runtime.h>
static NSString *completionKey = @"completionKey";
@implementation UIButton (Category1)
//通过运行时关联引用(见iOS小知识点02)
//以前还以为只是关联NSString那样的属性,现在想想,block块也是一种类型,既然是类型,就可以定义为 属性,那么应该是可以用运行时关联的吧。
- (void)setCompletion:(CompletionHandler)completion {
objc_setAssociatedObject(self, &completionKey, completion, OBJC_ASSOCIATION_COPY);
}
- (CompletionHandler)completion {
return objc_getAssociatedObject(self, &completionKey);
}
- (void)addActionForControlEvents:(UIControlEvents)controlEvents respond:(CompletionHandler)completion {
[self addTarget:self action:@selector(didClickButton) forControlEvents:controlEvents];
self.completion = completion;
}
- (void)didClickButton {
self.completion();
}
@end
方法三:通过分类的方式并使用运行时关联对象(缩减版)
在 UIButton+Category2.h
文件中的代码:
#import <UIKit/UIKit.h>
@interface UIButton (Category2)
- (void)addActionForControlEvents:(UIControlEvents)controlEvents respond:(void (^)())completion;
@end
在 UIButton+Category2.m
文件中的代码:
#import "UIButton+Category2.h"
#import <objc/runtime.h>
static NSString *completionKey = @"completionKey";
@implementation UIButton (Category2)
- (void)addActionForControlEvents:(UIControlEvents)controlEvents respond:(void (^)())completion {
[self addTarget:self action:@selector(didClickButton) forControlEvents:controlEvents];
objc_setAssociatedObject(self, &completionKey, completion, OBJC_ASSOCIATION_COPY);
}
- (void)didClickButton {
void (^block)() = objc_getAssociatedObject(self, &completionKey);
block();
}
@end
原理和方法二差不多,只是减少了一些代码量(本人较懒)。
在viewDidLoad中验证可行性
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[button setBackgroundColor:[UIColor blueColor]];
[button addActionForControlEvents:UIControlEventTouchUpInside respond:^{
NSLog(@"按钮被点击了");
}];
[self.view addSubview:button];