Lukas Kalinski
Lukas Kalinski

Reputation: 2243

How can I know when any of the objects on screen were tapped?

Now first of all, I am not asking how to add a gesture recognizer or how to create a button. What I want is to know that "somebody touched the screen in any way", without interfering with the related screen element.

The thing is that I have elements that the user can tap on (amazing, isn't it?). Then I have a view that is overlaid on top of everything (window addSubview). This view shows up with some delay, and I want the app to behave as if this view wasn't there until its "show" animation starts. Then, if the user taps any of the mentioned elements, which are not and cannot all be superviews to the overlaid view, the element should highlight and trigger as usual, while the view to be overlaid should cancel its show animation (alpha 0->1) and remove itself from the hierarchy.

tl;dr: How can I listen for any event for any object on the screen, without having to write explicit code to "watch" each of those objects — I just want to know that a gesture occured, not where, not how, not whatever? And I don't want to mess with the view that is the receiver of the event. Is this even possible?

Upvotes: 0

Views: 221

Answers (2)

matt
matt

Reputation: 535945

In your overlay view, override hitTest: as follows:

override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
    let result = super.hitTest(point, withEvent:event)
    if result === self {
        println("tapped the view")
        return nil
    }
    return result
}

The outcome is that if the overlay view is tapped, it responds (as proven by the "tapped the view" output to the console) but it allows the tap to fall through to whatever is behind it (because it returns nil). This is, in effect, an untouchable view that nevertheless knows when it is touched.

Upvotes: 2

Nirav Gadhiya
Nirav Gadhiya

Reputation: 6342

You need to just subclass your main window, and you will find all touch events there. There is a handy catch-all method in UIWindow called sendEvent: which sees every event near the start of the event-handling pipeline. If you want to do any non-standard additional event handling, this is a good place to put it. Something like this:

- (void)sendEvent:(UIEvent *)event {
  if ([self eventIsNoteworthy:event]) [self extraEventHandling:event];
  [super sendEvent:event];  // Apple says you must always call this!
}

Docs: UIWindow class reference | iOS event delivery docs

This blog post also mentions how to override hitTest:withEvent: to catch some events before they're bound to the target leaf subview in the view hierarchy. You can also override that method on your UIWindow object if you want.

Note : You will not get keyboard touch events through this solution.

Upvotes: 2

Related Questions