Understand UIResponder & Responder Chain to Handle Events

uikit Dec 06, 2022
Understand UIResponder & Responder Chain to Handle Events

In this article, you will learn how to handle events that communicate through the app.

What is UIResponder?

This is an abstract interface for responding to and handling events. An abstract interface is just combination of properties and methods to override them only. You can say, all the instances of UIResponder (responder objects) are the backbone of iOS apps. Here are some responder objects that are most commonly used:

  • UIView
  • UIViewController
  • UIControl
  • UIApplication

Note: You will learn about these components later in further articles.

How UIKit handle the events?

Once an event occurs, UIKit dispatches them to the app's responder objects for handling. UIKit manages most responder-related behavior automatically, including how events are delivered from one responder to the next.

There are several kinds of events, including touch events, motion events, remote-control events, and press events. To handle a specific type of event, a responder must override the corresponding methods. For example, to handle touch events, a responder implements the touchesBegan(), touchesMoved(), touchesEnded(), and touchesCancelled() methods. In the case of touches, the responder uses the event information provided by UIKit to track changes to those touches and to update the app's interface appropriately.

In addition to handling events, UIKit responders also manage the forwarding of unhandled events to other parts of your app. If a given responder does not handle an event, it forwards that event to the next event in the responder chain. UIKit manages the responder chain dynamically, using predefined rules to determine which object should be next to receive an event. For example, a view forwards events to its superview, and the root view of a hierarchy forwards events to its view controller.

Relation between UIResponder, UIEvent and UIControl

You know that responder objects can handle and respond to events (touch, motion, press).

An UIEvent represents a single UIKit event that contains a type (it may be touch, press, motion, etc). When an event has been detected in the system, UIKit internally creates a UIEvent instance and dispatch it to the system to perform. All events are sent in the queue by calling UIApplication.shared.sendEvent() method.

When an event comes to be performed from the queue, UIKit finds out the first UIResponder which is capable of handling the event, and sends it to the selected one.

You can also handle system events manually by creating the UIResponder's subclasses by overriding the specific methods:

// All UIResponder classes which are using the custom touch events should override these methods.
open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
open func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)
open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)
open func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?)


// All UIResponder classes which are using the custom press events should override these methods.
open func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?)
open func pressesChanged(_ presses: Set<UIPress>, with event: UIPressesEvent?)
open func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?)
open func pressesCancelled(_ presses: Set<UIPress>, with event: UIPressesEvent?)


// All UIResponder classes which are using custom motion like shake needs to override these methods.
open func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?)
open func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?)
open func motionCancelled(_ motion: UIEvent.EventSubtype, with event: UIEvent?)
open func remoteControlReceived(with event: UIEvent?)

Now, you know that UIEvents can be subclassed and sendEvent() can be manually called. Because you can not create custom event types (custom events may be problematic as they can be handled incorrectly by an unintended responder). Besides system events, UIResponders can also respond to "actions" in the form of Selectors - which is exactly performed using UIButton class which can dispatch actions after being touched.

Example:

let customButton = UIButton(type: .custom) // or .system
customButton.addTarget(targetView, action: #selector(method_name), for: .touchUpInside)

Here is a problem i.e. UIResponders can fully detect touch events and they are not easy to handle. So you will check which touch event has been occurred?

That's where UIControl (subclass of UIView) abstracts the process of handling touch events and provides the ability to assign actions to specific touch events.

Responder Chain

In iOS, Responder Chain is the name given to an UIKit-generated linked list of UIResponder objects.

The responder chain is responsible to handle all the events (like touch and motion) in iOS apps. If any responder can't handle a specific action or event, the event is sent to the next responder of the list to handle it until the list ends.

Responder chains in an app:

What next?

In this article, we explained how UIResponder works in the iOS apps and handles events. Now, let's dive into some basic UIKit components to learn the basics of them.

Signup now to get notified about our
FREE iOS Workshops!