子类化的替代方法是扩展 UIControl,向其添加 touchAreaInsets 属性 - 通过利用 objC 运行时 - 并调整 pointInside:withEvent。
#import <objc/runtime.h>
#import <UIKit/UIKit.h>
#import "NSObject+Swizzling.h" // This is where the magic happens :)
@implementation UIControl (Extensions)
@dynamic touchAreaInsets;
static void * CHFLExtendedTouchAreaControlKey;
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swizzleSelector:@selector(pointInside:withEvent:) withSelector:@selector(chfl_pointInside:event:) classMethod:NO];
});
}
- (BOOL)chfl_pointInside:(CGPoint)point event:(UIEvent *)event
{
if(UIEdgeInsetsEqualToEdgeInsets(self.touchAreaInsets, UIEdgeInsetsZero)) {
return [self chfl_pointInside:point event:event];
}
CGRect relativeFrame = self.bounds;
CGRect hitFrame = UIEdgeInsetsInsetRect(relativeFrame, self.touchAreaInsets);
return CGRectContainsPoint(hitFrame, point);
}
- (UIEdgeInsets)touchAreaInsets
{
NSValue *value = objc_getAssociatedObject(self, &CHFLExtendedTouchAreaControlKey);
if (value) {
UIEdgeInsets touchAreaInsets; [value getValue:&touchAreaInsets]; return touchAreaInsets;
}
else {
return UIEdgeInsetsZero;
}
}
- (void)setTouchAreaInsets:(UIEdgeInsets)touchAreaInsets
{
NSValue *value = [NSValue value:&touchAreaInsets withObjCType:@encode(UIEdgeInsets)];
objc_setAssociatedObject(self, &CHFLExtendedTouchAreaControlKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
这里是NSObject+Swizzling.h
https://gist.github.com/epacces/fb9b8e996115b3bfa735707810f41ec8
这是一个非常通用的界面,可以让您减少/增加UIControls 的触摸区域。
#import <UIKit/UIKit.h>
/**
* Extends or reduce the touch area of any UIControls
*
* Example (extends the button's touch area by 20 pt):
*
* UIButton *button = [[UIButton alloc] initWithFrame:CGRectFrame(0, 0, 20, 20)]
* button.touchAreaInsets = UIEdgeInsetsMake(-10.0f, -10.0f, -10.0f, -10.0f);
*/
@interface UIControl (Extensions)
@property (nonatomic, assign) UIEdgeInsets touchAreaInsets;
@end