How to pass UI events through views in iOS

This article will be very short, explain how to pass touch events on UI from a UIWindow/UIView instance to another one.

You might wonder if it’s worth to know? By default, in a trivial, common application, the top most view, which is determined by a fundamental mechanism implemented in UIKit called “hit-test”, will receive touch events. Hit-testing is no more an algorithm which goes through our view hierarchy and finds the deep most view that contains the touch point and should receive the event.

However, when your application has much more complicated UI, you might need to know other ways of handling touch events.



Here, I declare a subclass of UIView and override the default hitTest behavior. Then I can use this class whenever I want a view to be a passthrough view. Below is an example I can tap the underneath UISwitch.


An object that provides the backdrop for your app’s user interface and provides important event-handling behaviors. (Apple’s documentation).

In simply, a window is an object that contains UI elements on that. Every app must have at least 1 window which is usually initialized programmatically in code or by setting Is Initial View Controller in Storyboard.

It’s recommended that an app should have only 1 window, but there’re some cases we need more than that. For instance, when need another window to display things on an external screen. Or when using ReplayKit to broadcast our screen, the library captures our Main Window, if we want to show somethings not to be captured like stop button or capturing status, we must show them on another window.

Then we might need a way to pass touch events through windows. Fortunately, a UIWindow is just a UIView, so that we can declare like this:

For now, we can create a PassthroughWindow, or a PassthroughView and some subviews on that. However, what if the UI is not simple anymore: We need to display an window with a complex navigation controller on that (Well, it actually happened in my project).

Well, events are passed through the PassthroughView, but they will not be passed to PassthroughWindow because they will be stopped at middle views like BubblesViewController, UIViewControllerWrapperView, ... . We implemented PassthroughView but we can’t change these views’ class to PassthroughView or it would be very hard and frustrated to do. Here’s a trick to overcome this problem:

Whenever I hit-test a PassthroughView, I delegate the hit-test result to my PassthroughWindow. Of course, this special subclass will work only in this case, you may change the logic in your cases.

Where to go from here

Apart from hit testing, I also suggest you read about Responder Chain — an interesting way to alternate event responders.

iOS Engineer. Master student at University of Victoria.

iOS Engineer. Master student at University of Victoria.