我目前正在实施与分析相关的方案,这些方案将使用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;
}
可以看到,我添加了视图本身的日志,以查看在响应过程中正在检查哪些视图
结果是,即使单击的按钮响应了触摸事件,它也会被记录下来,好像忽略了它一样(两次)
这是日志输出(仅单击一次):
2014-06-15 16:58:07.393 Nutrino [63516:60b]视图-[UIButton:
0xcc92750;框架=(11 27; 20 16);不透明=不;层= [CALayer:
0xcc92360]]
2014-06-15 16:58:07.393 Nutrino [63516:60b]视图-[NRDiaryLogPlanView:
0xcc902b0;框架=(0 480; 320 88); gestureRecognizers = [NSArray:
0xcc92f90];层= [CALayer:0xcc908e0]]
2014-06-15 16:58:07.394 Nutrino [63516:60b]视图-[UIView:0xce79b00;
帧=(0 516; 320 568);层= [CALayer:0xce79b60]]
2014-06-15 16:58:07.394 Nutrino [63516:60b]视图-[UILabel:0xce799d0;
框架=(139.685 27; 40.63 20.264);文字=“日记”;隐藏=是;
userInteractionEnabled =否;层= [CALayer:0xce794b0]]
2014-06-15 16:58:07.395 Nutrino [63516:60b]视图-[UIView:0xce78900;
框架=(0 0; 540568); alpha = 0; gestureRecognizers = [NSArray:
0xcc92fc0];层= [CALayer:0xce78960]
2014-06-15 16:58:07.395 Nutrino [63516:60b]忽略:查看[[UIView:
0xce78900;框架=(0 0; 540568); alpha = 0; gestureRecognizers =
[NSArray:0xcc92fc0];层= [CALayer:0xce78960]]有类型的事件
[UITouchesEvent]指向(268,90),但被忽略。 2014-06-15
16:58:07.396 Nutrino [63516:60b]视图-[UIButtonLabel:0xce76c10;
框架=(21 4; 77 14);文字=“新卡”; clipsToBounds = YES;
不透明=不; userInteractionEnabled =否;层= [CALayer:
0xce76d60]]
2014-06-15 16:58:07.396 Nutrino [63516:60b]忽略:查看
[[UIButtonLabel:0xce76c10;框架=(21 4; 77 14);文字='新卡
'; clipsToBounds = YES;不透明=不; userInteractionEnabled =否;
layer = [CALayer:0xce76d60]]在以下类别中获得了[UITouchesEvent]类型的事件
点(22,8),但被忽略。 2014-06-15 16:58:07.397
Nutrino [63516:60b]视图-[UIImageView:0xce7ebc0;框架=(11.5 6; 10
10); clipsToBounds = YES;不透明=不; userInteractionEnabled =否;
层= [CALayer:0xce86a50]]
2014-06-15 16:58:07.397 Nutrino [63516:60b]视图-[UIButton:
0xce764c0;框架=(225 77; 110 22);不透明=不;层= [CALayer:
0xce76670]]
2014-06-15 16:58:07.397 Nutrino [63516:60b]视图-[NRCoachFeedView:
0xce67560;框架=(0 0; 540568);层= [CALayer:0xce65370]]
2014-06-15 16:58:07.398 Nutrino [63516:60b]视图-[UIView:0xce48c00;
框架=(0 0; 320568);层= [CALayer:0xce44980]
2014-06-15 16:58:07.398 Nutrino [63516:60b]视图-[UIView:0xcf55af0;
框架=(0 0; 320568);自动调整大小= RM + BM; autoresizesSubviews =否;
层= [CALayer:0xcf55470]
2014-06-15 16:58:07.399 Nutrino [63516:60b]视图-
[UIViewControllerWrapperView:0xcc93030;框架=(0 0; 320568);
自动调整大小= RM + BM;层= [CALayer:0xcc93100]
2014-06-15 16:58:07.399 Nutrino [63516:60b]视图-
[UINavigationTransitionView:0xcf48cf0;框架=(0 0; 320568);
clipsToBounds = YES;自动调整大小= W + H;层= [CALayer:0xcf48e10]]
2014-06-15 16:58:07.400 Nutrino [63516:60b]视图-
[UILayoutContainerView:0xcf40270;框架=(0 0; 320568);自动调整大小
= W + H; gestureRecognizers = [NSArray:0xcf4d680];层= [CALayer:0xcf3e570]
2014-06-15 16:58:07.400 Nutrino [63516:60b]视图-[UIView:0xcf40110;
框架=(0 0; 320568);自动调整大小= RM + BM; autoresizesSubviews =否;
层= [CALayer:0xcf3f980]]
2014-06-15 16:58:07.400 Nutrino [63516:60b]视图-[UIWindow:
0xce42c20;框架=(0 0; 320568);自动调整大小= W + H;
gestureRecognizers = [NSArray:0xce452b0];层= [UIWindowLayer:
0xce43aa0]]
2014-06-15 16:58:07.401 Nutrino [63516:60b]视图-[UIStatusBar:
0xd075600;帧=(0 0; 320 20); alpha = 0;隐藏=是;不透明=
没有;自动调整大小= W + BM;层= [CALayer:0xce30f50]]
2014-06-15 16:58:07.402 Nutrino [63516:60b]视图-[UIStatusBarWindow:
0xcc3ee20;框架=(0 0; 320568); gestureRecognizers = [NSArray:
0xcc3fdc0];层= [UIWindowLayer:0xcc3f060]]
2014-06-15 16:58:07.402 Nutrino [63516:60b]视图-[UIButton:
0xcc92750;框架=(11 27; 20 16);不透明=不;层= [CALayer:
0xcc92360]]
2014-06-15 16:58:07.403 Nutrino [63516:60b]视图-[NRDiaryLogPlanView:
0xcc902b0;框架=(0 480; 320 88); gestureRecognizers = [NSArray:
0xcc92f90];层= [CALayer:0xcc908e0]]
2014-06-15 16:58:07.403 Nutrino [63516:60b]视图-[UIView:0xce79b00;
帧=(0 516; 320 568);层= [CALayer:0xce79b60]]
2014-06-15 16:58:07.403 Nutrino [63516:60b]视图-[UILabel:0xce799d0;
框架=(139.685 27; 40.63 20.264);文字=“日记”;隐藏=是;
userInteractionEnabled =否;层= [CALayer:0xce794b0]]
2014-06-15 16:58:07.404 Nutrino [63516:60b]视图-[UIView:0xce78900;
框架=(0 0; 540568); alpha = 0; gestureRecognizers = [NSArray:
0xcc92fc0];层= [CALayer:0xce78960]
2014-06-15 16:58:07.404 Nutrino [63516:60b]忽略:查看[[UIView:
0xce78900;框架=(0 0; 540568); alpha = 0; gestureRecognizers =
[NSArray:0xcc92fc0];层= [CALayer:0xce78960]]有类型的事件
[UITouchesEvent]指向(268,90),但被忽略。 2014-06-15
16:58:07.405 Nutrino [63516:60b]视图-[UIButtonLabel:0xce76c10;
框架=(21 4; 77 14);文字=“新卡”; clipsToBounds = YES;
不透明=不; userInteractionEnabled =否;层= [CALayer:
0xce76d60]]
2014-06-15 16:58:07.405 Nutrino [63516:60b]忽略:查看
[[UIButtonLabel:0xce76c10;框架=(21 4; 77 14);文字='新卡
'; clipsToBounds = YES;不透明=不; userInteractionEnabled =否;
layer = [CALayer:0xce76d60]]在以下类别中获得了[UITouchesEvent]类型的事件
点(22,8),但被忽略。 2014-06-15 16:58:07.406
Nutrino [63516:60b]视图-[UIImageView:0xce7ebc0;框架=(11.5 6; 10
10); clipsToBounds = YES;不透明=不; userInteractionEnabled =否;
层= [CALayer:0xce86a50]]
2014-06-15 16:58:07.406 Nutrino [63516:60b]视图-[UIButton:
0xce764c0;框架=(225 77; 110 22);不透明=不;层= [CALayer:
0xce76670]]
2014-06-15 16:58:07.406 Nutrino [63516:60b]视图-[NRCoachFeedView:
0xce67560;框架=(0 0; 540568);层= [CALayer:0xce65370]]
2014-06-15 16:58:07.407 Nutrino [63516:60b]视图-[UIView:0xce48c00;
框架=(0 0; 320568);层= [CALayer:0xce44980]
2014-06-15 16:58:07.407 Nutrino [63516:60b]视图-[UIView:0xcf55af0;
框架=(0 0; 320568);自动调整大小= RM + BM; autoresizesSubviews =否;
层= [CALayer:0xcf55470]
2014-06-15 16:58:07.407 Nutrino [63516:60b]视图-
[UIViewControllerWrapperView:0xcc93030;框架=(0 0; 320568);
自动调整大小= RM + BM;层= [CALayer:0xcc93100]
2014-06-15 16:58:07.408 Nutrino [63516:60b]视图-
[UINavigationTransitionView:0xcf48cf0;框架=(0 0; 320568);
clipsToBounds = YES;自动调整大小= W + H;层= [CALayer:0xcf48e10]]
2014-06-15 16:58:07.408 Nutrino [63516:60b]视图-
[UILayoutContainerView:0xcf40270;框架=(0 0; 320568);自动调整大小
= W + H; gestureRecognizers = [NSArray:0xcf4d680];层= [CALayer:0xcf3e570]
2014-06-15 16:58:07.409 Nutrino [63516:60b]视图-[UIView:0xcf40110;
框架=(0 0; 320568);自动调整大小= RM + BM; autoresizesSubviews =否;
层= [CALayer:0xcf3f980]]
2014-06-15 16:58:07.409 Nutrino [63516:60b]视图-[UIWindow:
0xce42c20;框架=(0 0; 320568);自动调整大小= W + H;
gestureRecognizers = [NSArray:0xce452b0];层= [UIWindowLayer:
0xce43aa0]]
最佳答案
一种解决方法是包装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.
在这种情况下,我触摸了导航栏的标题。
希望这可以给您一个思路,以解决调试触摸问题。