为什么hitTest:withEvent:每次触摸调用三次?

时间:2011-07-01 15:40:24

标签: ios cocoa-touch event-handling

我有一个UIView的子类,其中我覆盖了hitTest:withEvent:,如下所示:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    NSLog(@"Event = %@", event);
    return self;
}

对于视图中的每次触摸,我看到三次调用hitTest:withEvent:。这三个电话是在修饰之前进行的。输出如下:

2011-07-01 09:20:58.553 AppName[930:207] Event = <UITouchesEvent: 0x6a08360> timestamp: 4297.16 touches: {(
)}
2011-07-01 09:20:58.553 AppName[930:207] Event = <UITouchesEvent: 0x6a08360> timestamp: 4297.16 touches: {(
)}
2011-07-01 09:20:58.554 AppName[930:207] Event = <UITouchesEvent: 0x6a08360> timestamp: 4304.54 touches: {(
)}

根据时间戳和地址,似乎正在使用单个UITouchesEvent对象,并且在第三次调用之前未正确设置其时间戳。任何人都可以解释为什么hitTest:withEvent:这样被调用三次?我不是在寻找一种解决方法。我只是想了解发生了什么。

4 个答案:

答案 0 :(得分:6)

我有同样的问题,并且能够使用此代码解决它。即使pointInside和hitTest被调用3次,触摸的UIView的touchesBegan(或touchesEnded)也会被调用一次。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{   
    if (event.type == UIEventTypeTouches)
        NSLog(@"%@", self);
}


- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if ([self pointInside:point withEvent:event])
        return self;

    return [super hitTest:point withEvent:event];
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    if (CGRectContainsPoint([self bounds], point))
    {
        if (event.type == UIEventTypeTouches)
        {           
            return YES;
        }
    }

    return NO;
}

答案 1 :(得分:4)

您有多个子视图吗?

来自文档:

此方法通过将pointInside:withEvent:消息发送到每个子视图来遍历视图层次结构,以确定哪个子视图应该接收触摸事件。如果pointInside:withEvent:返回YES,则遍历子视图的层次结构;否则,将忽略其视图层次结构的分支。您很少需要自己调用此方法,但可以覆盖它以隐藏子视图中的触摸事件。

答案 2 :(得分:0)

  

是的,这很正常。系统可能会在两次呼叫之间调整要命中测试的点。由于hitTest应该是没有副作用的纯函数,所以应该没问题。

请参阅Apple邮件列表:Re: -hitTest:withEvent: called twice?

答案 3 :(得分:-1)

您应该检查子类型和类型属性是否完全相同。这3个事件确实有意义,因为需要触发事件才能让操作系统理解触摸事件的性质。

例如,滑动,捏合和点击都以相同的触摸事件开始。我的猜测是,前两个被点燃1来注册点击事件,第二个点击测试点击事件“移动”。第二个被称为不久之后可能要么取消捏/缩放/其他。

最重要的是,文件描述了3种不同类型的事件:触摸,动作和远程事件。 UIEvent Class Reference