iOS Event Delivery Introduces And Example

When the iOS application starts, the UIApplicationMain function will create a single instance of a UIApplication. This single instance maintains a FIFO queue for event distribution. When the system detects a touch event, it will send the event to the current singleton application to distribute. The distribution is divided into three processes.

1. hitTest.

  1. Once UIWindow receives an event, it will perform a hit-test to find which object should receive the event.
  2. The method hitTest:withEvent is used to find the view at the touch location.
  3. The method pointInside :withEvent: is used to detect if the click is within the bounds of the view. hitTest:withEvent will call pointInside:withEvent:.
  4. hitTest is called recursively until the top leaf view that can handle touch events is found and is selected ( It’s usually the view of the region where the finger point at ). The view is also called the first responder.
  5. This process can be understood by set breakpoints in the below methods.
    - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event

2. sendEvent.

  1. Once the first responder is identified, the UIApplication singleton sends the associated touch event to the first responder.
  2. This process can be understood by setting a breakpoint at the code that processes this event. For example a button’s buttonPressed method.

3. Process Event.

  1. To handle a touch event you should override the following methods.
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; 
    - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; 
    - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event; 
    - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
  2. The first responder has three options after receiving the event.
  3. Do nothing ( not to overload the above method ).
  4. Handle some of it, and leave the rest to other objects ( Call super object’s related method at the end of each overridden method ).
  5. Process the event alone ( Do not call super object’s related method when override method ).
  6. If the first responder doesn’t handle anything, or handle parts and then calls the super method, the event will be sent through a chain-style response path which is called a response chain. This event is forwarded along the following path.
  7. First responder.
  8. The parent view of the first responder.
  9. The parent view of the parent view, up to the associated view controller.
  10. The parent view controller of the view controller is up to the root view.
  11. The next responder to the root view is a window.
  12. The next responder to the window is an application.
  13. The last responder was the App delegate.
  14. If it is forwarded to the App delegate, and the App delegate does not handle it, the event is discarded.

3.1 iOS Event Handling Priority.

  1. When you handle an iOS event, you should process the event in a subclass of UIControl, the event type can be a touch event or touch-related gesture.
  2. The gesture event will be processed first, if no gesture event is detected then the UIControl event such as ( button tap, button click ) will be triggered, if no such event has been captured, the TouchEvent will be processed.
  3. Below are the priorities for event handling.
    Touch Related Gesture Event ---> UIControl SubClass Event ---> Touch Event.

3.2 iOS Event Process Classification.

  1. If you want to change the event distribution process, you can implement the hitTest:withEvent: method for the related class.
  2. If you want to expand the scope of the click area, you can override pointInside:withEvent: method.
  3. To solve a problem such as putting away the keyboard, try sending an event directly like below.
    [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
  4. If you want the parent view or associated view controller to handle the event, you can use the below code.
    [button addTarget:nil action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.