I have a subclass of UIView
in which I've overridden hitTest:withEvent:
as follows:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(@"Event = %@", event);
return self;
}
For each touch in the view, I am seeing three calls to hitTest:withEvent:
. These three calls are made before touch up. The 开发者_C百科output is as follows:
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: {(
)}
Based on the timestamps and addresses, it appears as if a single UITouchesEvent
object is being used and its timestamp isn't properly set until the third call. Can anyone explain why hitTest:withEvent:
gets called three times like this? I'm not looking for a workaround. I just want to understand what's going on.
I had the same problem and was able to solve it with this code. Even though pointInside and hitTest get called 3 times, touchesBegan (or touchesEnded) of the UIView that was touched only gets called once.
- (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;
}
Do you have more than one subview?
From the docs:
This method traverses the view hierarchy by sending the pointInside:withEvent: message to each subview to determine which subview should receive a touch event. If pointInside:withEvent: returns YES, then the subview’s hierarchy is traversed; otherwise, its branch of the view hierarchy is ignored. You rarely need to call this method yourself, but you might override it to hide touch events from subviews.
Yes, it’s normal. The system may tweak the point being hit tested between the calls. Since hitTest should be a pure function with no side-effects, this should be fine.
Refer to Apple Mailing List: Re: -hitTest:withEvent: called twice?
You should check to see if the subtype and type property are all the same. those 3 events do make sense since there's event that needs to be triggered in order for the OS to understand the nature of the touch event.
For example, swipe, pinch and tap all start with the same touch event. My guess is that the first two are fired 1 to register the tap event and the second to test for tap event to "move". the second is called not long afterwards probably to either cancel the pinching/zooming/whatever.
Bottom line, the documentations talks about 3 different type of events: touch, motion and remote events. UIEvent Class Reference
精彩评论