2

I need to be able to detect any activity (i.e. not idle) so that I can reset a countdown timer.

I tried going the UIWindow sendEvent route but that's causing way too many side effects. Isn't there a simple way to detect if a view is tapped, button is clicked, the user navigates to the next screen, etc, etc? I don't need to handle the event or anything, I just need to reset the timer if the user is still using the navigation controller. Btw, this particularly navigation controller is being presented by another UIViewController in code.

I tried using UIGestureRecognizer to handle it, but unfortunately, this method doesn't seem to handle the UINavigationController's controls (e.g. next button, back, etc).

u84six
  • 4,604
  • 6
  • 38
  • 65
  • Possible duplicate of [Xcode & Swift - Detecting user touch of UIView inside of UIScrollView](http://stackoverflow.com/questions/25061732/xcode-swift-detecting-user-touch-of-uiview-inside-of-uiscrollview) – Grzegorz Krukowski Dec 06 '16 at 22:29
  • I've updated my question. The page you posted doesn't seem to help with UINavigationControllers. – u84six Dec 06 '16 at 22:45

1 Answers1

1

You can use own UIWindow subclass for this purpose and track user activity by one of the several UIResponder methods:

Any parent view can track subviews touch events. For example you can embed your UINavigationController to tracking parent view controller.

Or even place NonTouchableView over your screen by adding to window:

[self.view.window addSubview:myNonTouchableView];

Here is example of untouchable view, that can track touch events occurrences:

@interface NonTouchableView : UIView

@property (weak, nonatomic) id delegate;

@end

@implementation NonTouchableView

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    // Report user activity to self.delegate
    return nil;
}

@end

Swift version:

class NonTouchableView : UIView {

weak var delegate: Object?

func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    // Report user activity to delegate
    return nil
}

}
k06a
  • 17,755
  • 10
  • 70
  • 110
  • I would I do that in Swift? The problem with this approach is that I don't know which view controller is sending the event. So in my special case, I have a password screen that is presented by the same navigation controller and when I use the password screen, the hitTest is being fired and I don't want to reset the timer if it's the password screen being used. – u84six Dec 06 '16 at 23:12
  • You should dynamically add and remove `NonTouchableView` in `viewDidAppear` and `viewDidDisappear` of different view controllers you wanna track. You can write this code once in common parent view controller (`TrackableViewController`). Or implement more complicated logic of adding and removing this tracking views to hierarchy. – k06a Dec 06 '16 at 23:22
  • Is there a way I can do this without subclassing the UINavigationController? The reason I'm asking is because the UINavigationController is in a framework that I have no access to. All I do it present it and it collects and returns data. – u84six Dec 06 '16 at 23:29
  • @u84six yep, just add this view when you need to track, and hide it when not needed. Or you can add it once and enable/disable it with `hidden` property to easily start/stop tracking. – k06a Dec 06 '16 at 23:30