当UIButton的父容器有ScrollView的时候,button的点击高亮效果会失效,快速设置了highlighted = YES, highlighted = NO, 中间基本没时间间隔,所以看到不效果
分析:
UIScrollView 有个属性 delaysContentTouches,该值默认为 YES,属性的意思是 scrollView 在接收到手势时会延迟 300ms 来判断该手势是否能够触发 scrollView 的滑动事件;值为 NO 时 scrollView 会立刻将手势分发到子视图上。事件分发机制
设置 delaysContentTouches 为 NO 又会造成另外一个问题,如果拖动 scrollView 的手势触发到其他手势的视图上那么 scrollView 无法触发滚动事件
最简单解决方案:延迟设置高亮状态
@import ObjectiveC;
@implementation UIControl (TT_Control_Highlight)
+ (void)TT_exchangeMethod {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class clz = UIControl.class;
Method m0 = class_getInstanceMethod(clz, @selector(endTrackingWithTouch:withEvent:));
Method m1 = class_getInstanceMethod(clz, @selector(TT_endTrackingWithTouch:withEvent:));
NSParameterAssert(m0 && m1);
if (m0 && m1) {
method_exchangeImplementations(m0, m1);
}
});
}
- (BOOL)TT_useHighlight {
return [objc_getAssociatedObject(self, @selector(setTT_useHighlight:)) boolValue];
}
- (void)setTT_useHighlight:(BOOL)TT_useHighlight {
objc_setAssociatedObject(self, _cmd, @(TT_useHighlight), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if (TT_useHighlight) {
[self.class TT_exchangeMethod];
}
}
- (void)TT_endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
[self TT_endTrackingWithTouch:touch withEvent:event];
if (!self.TT_useHighlight) {
return;
}
if (!self.highlighted) {
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
self.highlighted = YES;
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.highlighted = NO;
});
}
@end
···