Tapas Pal
Tapas Pal

Reputation: 7207

UIWindow subclass: Touches event not get fired

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.

Upvotes: 2

Views: 1584

Answers (4)

jhabbott
jhabbott

Reputation: 19301

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.

Upvotes: 0

Himz
Himz

Reputation: 137

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

Upvotes: 0

Warif Akhand Rishi
Warif Akhand Rishi

Reputation: 24248

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

Upvotes: 0

L&#233;o Natan
L&#233;o Natan

Reputation: 57050

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.

Upvotes: 5

Related Questions