Skip to content

Instantly share code, notes, and snippets.

@WeZZard
Last active November 24, 2016 18:12
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WeZZard/1f07fbe3c931eb90a7b7 to your computer and use it in GitHub Desktop.
Save WeZZard/1f07fbe3c931eb90a7b7 to your computer and use it in GitHub Desktop.
Lively trace UIView's hit testing
//
// UIView+LiveHitTestTracing.h
// UIViewLiveHitTestTracing
//
// Created by Manfred on 10/28/15.
//
//
@import UIKit;
@interface UIView (LiveHitTestTracing)
+ (void)setLiveHitTestTracingEnabled:(BOOL)liveHitTestTracingEnabled;
+ (BOOL)isLiveHitTestTracingEnabled;
@end
//
// UIView+LiveHitTestTracing.m
// UIViewLiveHitTestTracing
//
// Created by Manfred on 10/28/15.
//
//
@import ObjectiveC;
#import "UIView+LiveHitTestTracing.h"
typedef UIView * ObjCRawCGPointUIEvent_UIView(UIView * self,
SEL selector,
CGPoint,
UIEvent *);
typedef ObjCRawCGPointUIEvent_UIView * ObjCRawCGPointUIEvent_UIViewRef;
ObjCRawCGPointUIEvent_UIViewRef original_hitTest_withEvent;
ObjCRawCGPointUIEvent_UIView swizzled_hitTest_withEvent;
BOOL isLiveHitTestTracingEnabled = NO;
@implementation UIView (LiveHitTestTracing)
+ (BOOL)isLiveHitTestTracingEnabled {
return isLiveHitTestTracingEnabled;
}
+ (void)setLiveHitTestTracingEnabled:(BOOL)liveHitTestTracingEnabled {
isLiveHitTestTracingEnabled = liveHitTestTracingEnabled;
}
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL selectorHitTestWithEvent =
NSSelectorFromString(@"hitTest:withEvent:");
original_hitTest_withEvent = (ObjCRawCGPointUIEvent_UIViewRef)
class_getMethodImplementation(self, selectorHitTestWithEvent);
IMP swizzled_hitTest_withEventIMP = (IMP)&swizzled_hitTest_withEvent;
class_replaceMethod(self,
selectorHitTestWithEvent,
swizzled_hitTest_withEventIMP ,
"@:{_struct=CGPoint}@");
});
}
- (void)showFootprintOfHitTesting {
UIColor * originalBackgroundColor = self.backgroundColor ?
self.backgroundColor : [UIColor clearColor];
UIViewKeyframeAnimationOptions animationOptions =
UIViewKeyframeAnimationOptionCalculationModeCubic
| UIViewKeyframeAnimationOptionAllowUserInteraction;
NSTimeInterval duration = 1.0;
[UIView animateKeyframesWithDuration: duration
delay: 0.0
options:animationOptions
animations:
^{
[UIView addKeyframeWithRelativeStartTime: 0
relativeDuration: duration * 0.5
animations:
^{
CGFloat hue = ( arc4random() % 256 / 256.0 );
CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5;
CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5;
UIColor * aRandomColor = [UIColor colorWithHue:hue
saturation:saturation
brightness:brightness
alpha:1];
self.backgroundColor = aRandomColor;
}];
[UIView addKeyframeWithRelativeStartTime: duration * 0.5
relativeDuration: duration * 0.5
animations:
^{
self.backgroundColor = originalBackgroundColor;
}];
}
completion: nil];
}
@end
UIView * swizzled_hitTest_withEvent(UIView * self,
SEL selector,
CGPoint point,
UIEvent * event)
{
if (UIView.isLiveHitTestTracingEnabled
&& ![self.superview isKindOfClass:[UIWindow class]])
{
[self.superview showFootprintOfHitTesting];
}
NSCAssert(original_hitTest_withEvent != NULL,
@"The original implementation of %@ should not be NULL",
NSStringFromSelector(selector));
UIView * testResult = (* original_hitTest_withEvent)(self,
selector,
point,
event);
if (testResult == self
&& UIView.isLiveHitTestTracingEnabled
&& ![self isKindOfClass:[UIWindow class]]) {
[self showFootprintOfHitTesting];
}
return testResult;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment