利用runtime和- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
方法给UIButton添加一个Category扩展按钮的点击范围
#import <UIKit/UIKit.h>
@interface UIButton (ICECategory)
- (void)expandClickAreaWithTop:(NSInteger)_top Right:(NSInteger)_right Bottom:(NSInteger)_bottom Left:(NSInteger)_left;
@end
#import "UIButton+ICECategory.h"
#import <objc/runtime.h>
@implementation UIButton (ICECategory)
static char topNameKey;
static char rightNameKey;
static char bottomNameKey;
static char leftNameKey;
/*
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,id _Nullable value, objc_AssociationPolicy policy)
key:要保证全局唯一,key与关联的对象是一一对应关系。必须全局唯一。通常用@selector(methodName)作为key。
value:要关联的对象。
policy:关联策略。有五种关联策略。
OBJC_ASSOCIATION_ASSIGN 等价于 @property(assign)。
OBJC_ASSOCIATION_RETAIN_NONATOMIC 等价于 @property(strong, nonatomic)。
OBJC_ASSOCIATION_COPY_NONATOMIC 等价于@property(copy, nonatomic)。
OBJC_ASSOCIATION_RETAIN 等价于@property(strong,atomic)。
OBJC_ASSOCIATION_COPY 等价于@property(copy, atomic)。
*/
- (void)expandClickAreaWithTop:(NSInteger)_top Right:(NSInteger)_right Bottom:(NSInteger)_bottom Left:(NSInteger)_left {
objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithInteger:_top], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithInteger:_right], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithInteger:_bottom], OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithInteger:_left], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGRect)expandedClickAre {
NSNumber *topNum = objc_getAssociatedObject(self, &topNameKey);
NSNumber *rightNum = objc_getAssociatedObject(self, &rightNameKey);
NSNumber *bottomNum = objc_getAssociatedObject(self, &bottomNameKey);
NSNumber *leftNum = objc_getAssociatedObject(self, &leftNameKey);
if (topNum && rightNum && bottomNum && leftNum) {
return CGRectMake(self.bounds.origin.x - leftNum.integerValue, self.bounds.origin.y - topNum.integerValue, self.bounds.size.width + leftNum.integerValue + rightNum.integerValue, self.bounds.size.height + topNum.integerValue + bottomNum.integerValue);
}
else {
return self.bounds;
}
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
CGRect rect = [self expandedClickAre];
if (CGRectEqualToRect(rect, self.bounds)) {
return [super hitTest:point withEvent:event];
}
else {
return CGRectContainsPoint(rect, point)? self: nil;
}
}