1

I want to be able to recognise ALL touches in an interface, no matter what was touched.

I've tried:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

.. but this just recognises when the user taps on something that doesn't respond to taps (uiimages for instance)

The reason i need this ability is that I want to kick in a slide show if the user doesn't touch the screen for 5 minutes, so I want to reset the timer whenever they touch. It seems wrong to put this reset code in each UI event individually.

cannyboy
  • 24,180
  • 40
  • 146
  • 252

5 Answers5

3

You could subclass UIWindow and override the sendEvent: method.

omz
  • 53,243
  • 5
  • 129
  • 141
3

There are several possible solutions, but as said @omz - overriding the sendEvent: it is the best one.

@interface YourWindow : UIWindow {
    NSDate timeOfLastTouch;
}
@end

@implementation YourWindow
 - (void)sendEvent:(UIEvent *)event {
    [super sendEvent:event];

    NSSet *touches = [event allTouches];
      UITouch *touch = [touches anyObject];
    if( touch.phase == UITouchPhaseEnded ){
         timeOfLastTouch = [NSDate date];
    }
} 



@end

Do not forget replace UIWindow with YourWindow.

johndpope
  • 5,035
  • 2
  • 41
  • 43
SVGreg
  • 2,320
  • 1
  • 13
  • 17
1

As @Alladinian said in one of the comments, iOS Reference Documentation mentions that subclassing UIApplication is the right application and thus, seems preferred to subclassing UIWindow. cf. https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIApplication_Class/Reference/Reference.html :

You might decide to subclass UIApplication to override sendEvent: or sendAction:to:from:forEvent: to implement custom event and action dispatching.

Mick F
  • 7,312
  • 6
  • 51
  • 98
  • This is the correct answer! For subclassing of application you can also check: http://stackoverflow.com/questions/1399202/how-to-subclass-uiapplication – Alex Oct 15 '14 at 21:40
1

You can subclass the UIWindow and override the sendEvent: method like this:

- (void)sendEvent:(UIEvent *)event {
  if (event.type == UIEventTypeTouches) {
     // You got a touch, do whatever you like
  };

  [super sendEvent:event];  // Let the window do the propagation of the event
}
Klaas
  • 22,394
  • 11
  • 96
  • 107
Alladinian
  • 34,483
  • 6
  • 89
  • 91
  • @omz Sorry I just saw your answer... I was typing mine at the same time :P – Alladinian Apr 03 '12 at 13:38
  • You mean in the app delegate instead one the standard UIWindow *window? Since I don't want this to trigger in every part of the app (just most) it seems better to do this per ViewController.. is there a way to do that? – cannyboy Apr 03 '12 at 13:43
  • 1
    As far as I know it's difficult to implement this into separate UIViewControllers. The reason is that the first responder for any event (including touches) is the `UIApplication`. Then the event is propagated to the UIWindow and then it tries to find the view (a `UIResponder` subclass) to handle the event. So if you want to catch all the touch events I think the best approach is to create a subclass of `UIWindow` (or `UIApplication`) – Alladinian Apr 03 '12 at 13:56
  • subclassing `UIWindow` and then using `NSNotificationCenter` to notify the specific viewController would be a good way to go – EagerMike Apr 03 '12 at 13:59
1

you could use a tap gesture

In your interface add the UIGestureRecognizerDelegate

@interface ViewController : UIViewController <UIGestureRecognizerDelegate> {

then in your viewDidLoad add this

UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapMethod)];
tapped.delegate=self;
tapped.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tapped];

then do your timer code in the tapped method

-(void)tapped {
 //timer code
}

Make sure you UI elements have setUserInteractionEnabled:YES

EagerMike
  • 2,032
  • 1
  • 24
  • 40