我目前正在实施使用Localytics触发事件的与分析相关的方案。
我想跟踪每一个"错误"手势,这意味着如果用户点击了他认为可以点击的东西(但是没有),或者他认为可以平移的观点(但是没有)。
我究竟能如何追踪这些错误的手势?
编辑 - 试图让Leo Natan的回答工作
我已使用以下方法在UIView类上添加了扩展
@implementation UIView (NRExtensions)
#pragma mark - finding unresponsive touches
+ (void)load {
Method orig = class_getInstanceMethod([UIView class], @selector(hitTest:withEvent:));
Method debg = class_getInstanceMethod([UIView class], @selector(_swiz_hitTest:withEvent:));
method_exchangeImplementations(orig, debg);
}
- (UIView *)_swiz_hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
//Will actually call the original implementation of the method, not infinite recursion.
UIView* hitTestObj = [self _swiz_hitTest:point withEvent:event];
NSLog(@"View - %@\n\n",self);
if(hitTestObj == nil && [self pointInside:point withEvent:event])
{
NSLog(@"\nIGNORING :View <%@> got event of type <%@> in point (%.0f,%.0f) but was ignored.\n", self, [event class], point.x, point.y);
}
return hitTestObj;
}
可以看出,我添加了一个视图本身的日志,以查看在回复的过程中正在检查哪些视图
结果是,即使点击的按钮响应了触摸事件,它也会被记录,好像它忽略了它(两次)
这是日志输出(只需单击1次):
2014-06-15 16:58:07.393 Nutrino [63516:60b]查看 - [UIButton: 0xcc92750; frame =(11 27; 20 16); opaque = NO; layer = [CALayer: 0xcc92360]
2014-06-15 16:58:07.393 Nutrino [63516:60b]查看 - [NRDiaryLogPlanView: 0xcc902b0; frame =(0 480; 320 88); gestureRecognizers = [NSArray: 0xcc92f90]; layer = [CALayer:0xcc908e0]]
2014-06-15 16:58:07.394 Nutrino [63516:60b]查看 - [UIView:0xce79b00; frame =(0 516; 320 568); layer = [CALayer:0xce79b60]]
2014-06-15 16:58:07.394 Nutrino [63516:60b]查看 - [UILabel:0xce799d0; frame =(139.685 27; 40.63 20.264); text =&#39; Diary&#39 ;; hidden = YES; userInteractionEnabled = NO; layer = [CALayer:0xce794b0]]
2014-06-15 16:58:07.395 Nutrino [63516:60b]查看 - [UIView:0xce78900; frame =(0 0; 540 568); alpha = 0; gestureRecognizers = [NSArray: 0xcc92fc0]; layer = [CALayer:0xce78960]]
2014-06-15 16:58:07.395 Nutrino [63516:60b] IGNORING:查看[[UIView: 0xce78900; frame =(0 0; 540 568); alpha = 0; gestureRecognizers = [NSArray:0xcc92fc0]; layer = [CALayer:0xce78960]]]得到了类型的事件 [UITouchesEvent]点(268,90)但被忽略了。 2014年6月15日 16:58:07.396 Nutrino [63516:60b]查看 - [UIButtonLabel:0xce76c10; frame =(21 4; 77 14); text =&#39;新卡&#39 ;; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = [CALayer: 0xce76d60]
2014-06-15 16:58:07.396 Nutrino [63516:60b] IGNORING:查看 [[UIButtonLabel:0xce76c10; frame =(21 4; 77 14); text =&#39;新卡 &#39 ;; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = [CALayer:0xce76d60]]]得到[UITouchesEvent]类型的事件 点(22,8)但被忽略了。 2014-06-15 16:58:07.397 Nutrino [63516:60b]查看 - [UIImageView:0xce7ebc0; frame =(11.5 6; 10 10); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = [CALayer:0xce86a50]]
2014-06-15 16:58:07.397 Nutrino [63516:60b]查看 - [UIButton: 0xce764c0; frame =(225 77; 110 22); opaque = NO; layer = [CALayer: 0xce76670]
2014-06-15 16:58:07.397 Nutrino [63516:60b]查看 - [NRCoachFeedView: 0xce67560; frame =(0 0; 540 568); layer = [CALayer:0xce65370]]
2014-06-15 16:58:07.398 Nutrino [63516:60b]查看 - [UIView:0xce48c00; frame =(0 0; 320 568); layer = [CALayer:0xce44980]]
2014-06-15 16:58:07.398 Nutrino [63516:60b]查看 - [UIView:0xcf55af0; frame =(0 0; 320 568); autoresize = RM + BM; autoresizesSubviews = NO; layer = [CALayer:0xcf55470]]
2014-06-15 16:58:07.399 Nutrino [63516:60b]查看 - [UIViewControllerWrapperView:0xcc93030; frame =(0 0; 320 568); autoresize = RM + BM; layer = [CALayer:0xcc93100]]
2014-06-15 16:58:07.399 Nutrino [63516:60b]查看 - [UINavigationTransitionView:0xcf48cf0; frame =(0 0; 320 568); clipsToBounds = YES; autoresize = W + H; layer = [CALayer:0xcf48e10]]
2014-06-15 16:58:07.400 Nutrino [63516:60b]查看 - [UILayoutContainerView:0xcf40270; frame =(0 0; 320 568); AUTORESIZE = W + H; gestureRecognizers = [NSArray:0xcf4d680]; layer = [CALayer:0xcf3e570]]
2014-06-15 16:58:07.400 Nutrino [63516:60b]查看 - [UIView:0xcf40110; frame =(0 0; 320 568); autoresize = RM + BM; autoresizesSubviews = NO; layer = [CALayer:0xcf3f980]]
2014-06-15 16:58:07.400 Nutrino [63516:60b]查看 - [UIWindow: 0xce42c20; frame =(0 0; 320 568); autoresize = W + H; gestureRecognizers = [NSArray:0xce452b0]; layer = [UIWindowLayer: 0xce43aa0]
2014-06-15 16:58:07.401 Nutrino [63516:60b]查看 - [UIStatusBar: 0xd075600; frame =(0 0; 320 20); alpha = 0; hidden = YES;不透明= 没有; autoresize = W + BM; layer = [CALayer:0xce30f50]]
2014-06-15 16:58:07.402 Nutrino [63516:60b]查看 - [UIStatusBarWindow: 0xcc3ee20; frame =(0 0; 320 568); gestureRecognizers = [NSArray: 0xcc3fdc0]; layer = [UIWindowLayer:0xcc3f060]]
2014-06-15 16:58:07.402 Nutrino [63516:60b]查看 - [UIButton: 0xcc92750; frame =(11 27; 20 16); opaque = NO; layer = [CALayer: 0xcc92360]
2014-06-15 16:58:07.403 Nutrino [63516:60b]查看 - [NRDiaryLogPlanView: 0xcc902b0; frame =(0 480; 320 88); gestureRecognizers = [NSArray: 0xcc92f90]; layer = [CALayer:0xcc908e0]]
2014-06-15 16:58:07.403 Nutrino [63516:60b]查看 - [UIView:0xce79b00; frame =(0 516; 320 568); layer = [CALayer:0xce79b60]]
2014-06-15 16:58:07.403 Nutrino [63516:60b]查看 - [UILabel:0xce799d0; frame =(139.685 27; 40.63 20.264); text =&#39; Diary&#39 ;; hidden = YES; userInteractionEnabled = NO; layer = [CALayer:0xce794b0]]
2014-06-15 16:58:07.404 Nutrino [63516:60b]查看 - [UIView:0xce78900; frame =(0 0; 540 568); alpha = 0; gestureRecognizers = [NSArray: 0xcc92fc0]; layer = [CALayer:0xce78960]]
2014-06-15 16:58:07.404 Nutrino [63516:60b]忽略:查看[[UIView: 0xce78900; frame =(0 0; 540 568); alpha = 0; gestureRecognizers = [NSArray:0xcc92fc0]; layer = [CALayer:0xce78960]]]得到了类型的事件 [UITouchesEvent]点(268,90)但被忽略了。 2014年6月15日 16:58:07.405 Nutrino [63516:60b]查看 - [UIButtonLabel:0xce76c10; frame =(21 4; 77 14); text =&#39;新卡&#39 ;; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = [CALayer: 0xce76d60]
2014-06-15 16:58:07.405 Nutrino [63516:60b] IGNORING:查看 [[UIButtonLabel:0xce76c10; frame =(21 4; 77 14); text =&#39;新卡 &#39 ;; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = [CALayer:0xce76d60]]]得到[UITouchesEvent]类型的事件 点(22,8)但被忽略了。 2014-06-15 16:58:07.406 Nutrino [63516:60b]查看 - [UIImageView:0xce7ebc0; frame =(11.5 6; 10 10); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = [CALayer:0xce86a50]]
2014-06-15 16:58:07.406 Nutrino [63516:60b]查看 - [UIButton: 0xce764c0; frame =(225 77; 110 22); opaque = NO; layer = [CALayer: 0xce76670]
2014-06-15 16:58:07.406 Nutrino [63516:60b]查看 - [NRCoachFeedView: 0xce67560; frame =(0 0; 540 568); layer = [CALayer:0xce65370]]
2014-06-15 16:58:07.407 Nutrino [63516:60b]查看 - [UIView:0xce48c00; frame =(0 0; 320 568); layer = [CALayer:0xce44980]]
2014-06-15 16:58:07.407 Nutrino [63516:60b]查看 - [UIView:0xcf55af0; frame =(0 0; 320 568); autoresize = RM + BM; autoresizesSubviews = NO; layer = [CALayer:0xcf55470]]
2014-06-15 16:58:07.407 Nutrino [63516:60b]查看 - [UIViewControllerWrapperView:0xcc93030; frame =(0 0; 320 568); autoresize = RM + BM; layer = [CALayer:0xcc93100]]
2014-06-15 16:58:07.408 Nutrino [63516:60b]查看 - [UINavigationTransitionView:0xcf48cf0; frame =(0 0; 320 568); clipsToBounds = YES; autoresize = W + H; layer = [CALayer:0xcf48e10]]
2014-06-15 16:58:07.408 Nutrino [63516:60b]查看 - [UILayoutContainerView:0xcf40270; frame =(0 0; 320 568); AUTORESIZE = W + H; gestureRecognizers = [NSArray:0xcf4d680]; layer = [CALayer:0xcf3e570]]
2014-06-15 16:58:07.409 Nutrino [63516:60b]查看 - [UIView:0xcf40110; frame =(0 0; 320 568); autoresize = RM + BM; autoresizesSubviews = NO; layer = [CALayer:0xcf3f980]]
2014-06-15 16:58:07.409 Nutrino [63516:60b]查看 - [UIWindow: 0xce42c20; frame =(0 0; 320 568); autoresize = W + H; gestureRecognizers = [NSArray:0xce452b0]; layer = [UIWindowLayer: 0xce43aa0]
答案 0 :(得分:4)
解决此问题的一种方法是包装hitTest:withEvent:
的实现,并在某些条件下打印调试输出。
@interface UIView (DebugHitTest) @end
@implementation UIView (DebugHitTest)
+ (void)load
{
Method orig = class_getInstanceMethod([UIView class], @selector(hitTest:withEvent:));
Method debg = class_getInstanceMethod([UIView class], @selector(_swiz_hitTest:withEvent:));
method_exchangeImplementations(orig, debg);
}
- (UIView *)_swiz_hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
//Will actually call the original implementation of the method, not infinite recursion.
UIView* hitTestObj = [self _swiz_hitTest:point withEvent:event];
if(hitTestObj == nil && [self pointInside:point withEvent:event])
{
NSLog(@"View <%@> got event of type <%@> but was ignored.", self, [event class]);
}
return hitTestObj;
}
@end
这给你的目的是查看在视图内部开始但由于某些条件而被忽略的触摸事件(默认情况下,当视图被隐藏,禁用,禁用用户交互或alpha小于0.01时,iOS会忽略事件。
您将看到如下输出:
View <<UINavigationItemView: 0xe7cd560; frame = (138 8; 44.5 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xe7d2360>>> got event of type <UITouchesEvent> but was ignored.
View <<_UINavigationBarBackground: 0xe771070; frame = (0 -20; 320 64); opaque = NO; autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0xe7bb010>>> got event of type <UITouchesEvent> but was ignored.
View <<UINavigationItemView: 0xe7cd560; frame = (138 8; 44.5 27); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xe7d2360>>> got event of type <UITouchesEvent> but was ignored.
View <<_UINavigationBarBackground: 0xe771070; frame = (0 -20; 320 64); opaque = NO; autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0xe7bb010>>> got event of type <UITouchesEvent> but was ignored.
在这种情况下,我触摸了导航栏的标题。
希望这能让您了解如何调试触摸问题。