2

I want to implement session time feature in my current project. So for that I am trying to subclass UIWindow and override the touchesBegan and touchesEnded methods.

class BaseWindow: UIWindow {

    convenience init() {
        self.init(frame: UIScreen.mainScreen().bounds)
    }

    private var sessionTimeOutTimer: NSTimer?

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        sessionTimeOutTimer?.invalidate()
    }

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        sessionTimeOutTimer = NSTimer.scheduledTimerWithTimeInterval(60, target: CIAppManager.sharedManger(), selector: #selector(CIAppManager.sessionTimeOut), userInfo: nil, repeats: false)
    }
}

In app delegate I did this

private let baseWindow = BaseWindow()
var window: UIWindow? {
    get {
        return baseWindow
    }
    set {}
}

But the problem is touchesBegan and touchesEnded are not get called. I am not able to figure out what's I am doing wrong.

shim
  • 9,289
  • 12
  • 69
  • 108
Tapas Pal
  • 7,073
  • 8
  • 39
  • 86
  • Maybe this project will be helpful to you: https://github.com/marqeta/mqtimeout – shim Sep 09 '16 at 14:40
  • show us your entire _app delegate_ file, please, because I have a very bad feeling about the `private let baseWindow = ...` line, that does not seem serving any reasonable purpose, so, please, the __entire__ file would be more talkative. – holex Sep 09 '16 at 14:49

4 Answers4

5

The touchesBegan(_:with:) API will not be called for your window, unless there is no one else to capture the touch event. This is normally never the case, as you want your UI elements to receive touches.

What you want to implement in your window subclass is sendEvent(:_) and put your logic there. Don't forget to call the super implementation to pass the events.

A small ceveat with this approach is you will hear some events which are not touch events, but that may not be a problem, as they are mostly user generated anyway.

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
0

Instead of subclassing UIWindow. You can add UITapGestureRecognizer in AppDelegate's window.

let gestureRecogniger = UITapGestureRecognizer(target: self, action: #selector(yourSelector)) // Implement your selector
gestureRecogniger.cancelsTouchesInView = false
window?.addGestureRecognizer(gestureRecogniger)

If you need to consider other touches other than taps use UIPanGestureRecognizer and UITapGestureRecognizer together.

If you have subviews that have their own gesture recognizers add this extension

extension AppDelegate: UIGestureRecognizerDelegate {
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

and do

gestureRecogniger.delegate = self
Warif Akhand Rishi
  • 23,920
  • 8
  • 80
  • 107
  • This will only catch taps, not touches. It will also not play well with subviews that have their own gesture recognizers. – Léo Natan Sep 04 '16 at 19:25
  • wow rain of negative votes. :) Its amazing how different people use votes differently. Anyways.. there are way around the issues you stated. see my updated answer. – Warif Akhand Rishi Sep 05 '16 at 05:59
0

I have tried to subclass UIWindow and override the methods touchesBegan, touchesEnded these methods are getting called when window is having a rootViewController check the demo project. Sample app TouchTest

Also check this method - (void)sendEvent:(UIEvent *)event

As per documentation : you might call this method to dispatch a custom event to the window’s responder chain. Window objects dispatch touch events to the view in which the touch occurred, and dispatch other types of events to the most appropriate target object

Himz
  • 137
  • 7
0

A better way to track sessions would be to register for UIApplication notifications, such as UIApplicationDidEnterBackgroundNotification and UIApplicationDidFinishLaunchingNotification.

The full list of application notifications is available at the bottom of the UIApplication class reference. You can create a session tracker class that listens for these cleanly without interfering with other parts of your code.

jhabbott
  • 18,461
  • 9
  • 58
  • 95