Search code examples
iosuiviewuigesturerecognizeruitouchuievent

Capturing and recording touch events on UIView


I'm trying to subclass UIView and design a transparent view. This view will sit on top of many other views and it's only task is to capture and record user touches (tap and pan). I have tried many different methods, explained in different questions asked by other users with no luck. This is what I have done so far in my implementation file:

#import "touchLayer.h"

@implementation touchLayer

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) [self commonInit];
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) [self commonInit];
    return self;
}

- (void)commonInit
{
    self.userInteractionEnabled = YES;
    self.alpha = 0.0;
}

- (id)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    id hitView = [super hitTest:point withEvent:event];
    if (hitView == self)
    {
        UITouch *touch = [[event allTouches] anyObject];

        if (touch.phase == UITouchPhaseBegan) NSLog(@"touchesBegan");
        else if (touch.phase == UITouchPhaseMoved) NSLog(@"touchesMoved");
        else if (touch.phase == UITouchPhaseEnded) NSLog(@"touchesEnded");

        return nil;
    }
    else
        return hitView;
}

@end

Now this code works just fine, and I see see the touches in the lower layers, but I cannot differentiate between touchBegan, touchMoved, and touchEnded. [[event allTouches] anyObject] returns nil. Do you have any idea how I can capture tap and pan on a UIView without blocking the touches? Thanks a lot.


Solution

  • After investigating, actually i can't find solution to detect touch using hitTest method with a touchLayer. But your question is about capturing and recording user touches, so i have another for this issue.

    My solution is

    • Subclass UIWindow
    • Replace window of UIAppDelegate with a new one which is created with your window class.
    • Override sendEvent method of UIWindow, capture and record user touches in this method.

    This is my subclass of UIWindow to detect touch. I tried and it work.

    @implementation DetectTouchWindow
    
    - (void)sendEvent:(UIEvent *)event {
      UITouch *touch = [[event allTouches] anyObject];
    
      switch ([touch phase]) {
        case UITouchPhaseBegan:
          NSLog(@"Touch Began");
          break;
        case UITouchPhaseMoved:
          NSLog(@"Touch Move");
          break;
        case UITouchPhaseEnded:
          NSLog(@"Touch End");
          break;
        case UITouchPhaseCancelled:
          NSLog(@"Touch Cancelled");
          break;
        default:
          break;
      }
    
      [super sendEvent:event];
    }
    
    @end
    

    For more detail and easier, i created a demo repo to check it. You can take a look at this link https://github.com/trungducc/stackoverflow/tree/recording-touch-events

    Hope this helps ;)