Do we need to explicitly register all high-level interaction events for every widget in UIKit?

I have a question about how UIKit expects us to handle interaction events at scale.

From what I understand so far:

  • For UIControls (UIButton, UISwitch, UITextField, etc.), we explicitly register with addTarget(_:action:for:).
  • For gestures, we add UIGestureRecognizer instances to views.
  • For UIView subclasses, we can override touch methods like touchesBegan/touchesEnded.

All of this must be done on the main thread, since UIKit isn’t thread-safe.

Now here’s my main concern

If I have a complex UI with hundreds or thousands of widgets, am I expected to perform these registrations individually for each widget and each high-level event (tap, long press, editing changed, etc.)?

Or does UIKit provide a more centralized mechanism?

In short: Is per-widget, per-event registration the “normal” UIKit approach, or are there best practices for scaling event handling without writing thousands of addTarget or addGestureRecognizer calls?

Thanks!

It is fair uncommon to need widespread handling of all kinds of events/control events for every kind of view. As such the answer is – at least for the common case – no, we would not expect you to register for everything or need to.

But I think its going to be very difficult to answer your question in a satisfactory way without understanding what you are trying to do and why you think you need to handle so many events.

For most controls for example, the only event you should ever need to register for is primaryActionTriggered. For most views you don't need explicit touch handling, but if you do adding an appropriate gesture recognizer with its specific handler is generally sufficient.

At the end of the day though, these registrations are not expected to be performance sensitive enough that its a problem to do them all on the main thread. But your commenting on needing "thousands" of these is concerning simply because it is exceedingly uncommon to need to handle thousands of different kinds of gestures on screen at once.

If I have a complex UI with hundreds or thousands of widgets, am I expected to perform these registrations

You perform the registrations you need based on what you are doing.

So, if you decide to use a UIControl, then yes, you need to decide which UIControlEvent you need. As mentioned above, that's likely just primaryActionTriggered, though.

And for UIView's, unless you have legacy code where you are handling responder-based delivery like touchesBegan:, touchesEnded: you should prefer UIGestureRecognizer instead.

That could be one of our pre-packaged gestures, like UITapGestureRecognizer or UILongPressGestureRecognizer, or you could write your own subclass with the event protocols mentioned in UIGestureRecognizerSubclass.h.

There is no centralized place "recognize all the things", because not all gestures are needed all the time. For simple tapping of something on screen, you do not need UITapGestureRecognizer, UILongPressGestureRecognizer, UIPanGestureRecognizer, and UIPinchGestureRecognizer. You only need UITapGestureRecognizer. You set these up, or create your own, based on what you want the user to do to trigger the desired behavior.

or are there best practices for scaling event handling without writing thousands of addTarget or addGestureRecognizer calls?

As mentioned above, you should not be writing thousands of these. It would be good to hear more about what you are trying to do.

And in terms of performance, there are some extremely complicated gesture environments in our operating systems. You will not hit the boundaries of this in a normal application.

I’m building a complex application with a rich UI, and I need to handle granular events at multiple levels — UIControl events, UIGestureRecognizer events, and even subclass-level events depending on the use case.

For UIControl, I often need to respond to granular events such as .touchUpInside, .touchDown, .touchCancel, etc., which are not fully covered by .primaryActionTriggered. From my understanding, .primaryActionTriggered does not actually reduce the number of addTarget(_:action:for:) calls I need to write — it only simplifies the choice of which event constant to use for a control’s primary action.

So in practice, if my use case requires handling these diverse low-level events, I would still need to explicitly register for each event on each control.

Is this the correct understanding?

Do we need to explicitly register all high-level interaction events for every widget in UIKit?
 
 
Q