事件传递和响应机制

iOS 事件传递和响应机制

一.概述

APPs通过responder objects来接收和处理点击事件,responder

Object是UIResponder类的实例。同时UIView,UIViewController,UIApplication

也是UIResponder类的子类。

事件的传递过程就是寻找first responder的过程,传递过程是从父控件到子控件逐层寻找第一响应者(UIApplication-> window->最合适的view)。找到firstResponder之后开始进行事件响应的过程,也就是说响应链的这顺序正好和事件的传递顺序相反,从子控件沿着响应链一直到响应链末端的父控件。

二. 响应链的传递过程

        1.响应链的传递过程如下图:

下图展示一个简易的APP,包含UILabel, UITextFileld, UIButton,UIView,UIViewController。如图示,响应链从上向下传递,传递到能响应的层级截止,如均无发响应这个事件,相当于系统放弃该事件。

Figure 1-1

2.响应链中的事件处理方法

系统为UIView触摸事件处理提供了四个方法

(1)- (void)touchesBegan:(NSSet<UITouch*> *)touches withEvent:(UIEvent*)event;

Tells this object that one or more new touches occurred in a view or window.

(2)- (void)touchesCancelled:(NSSet<UITouch*> *)touches withEvent:(UIEvent*)event;

Tells the responder when a system event (such as a system alert) cancels a touch sequence.

(3)- (void)touchesMoved:(NSSet<UITouch*> *)touches withEvent:(UIEvent*)event;

Tells the responder when one or more touches associated with an event changed.

(4)- (void)touchesEnded:(NSSet<UITouch*> *)touches withEvent:(UIEvent*)event;

Tells the responder when one or more fingers are raised from a view or window. 注意:如果是UIVIew的触摸事件需要自定义继承于UIView的子类,在子类中写这四个方法。如果是UIViewController的触摸事件直接在viewController中重写这四个方法就可以了。

三.寻找事件的firstResponder

1.具体步骤

点击屏幕,发生点击事件,UIKIt开始处理点击事件,事件传递方向UIApplication->keyWindow->viewController->rootView->view->subView,按照事件传递方向寻找最合适的响应者,firstResponder。下面详细介绍fUIView的irstResponder寻找过程。

(1)首先判断keyWindow是否能响应触摸事件或者说触摸事件是否在keyWindow范围内,如果不在则直接放弃后续查找

(2)UIKit通过遍历view hierarchy寻找the deepest subview作为firstResponder

下图是官方文档提供的解释


Figure 1-2

(3)view hierarchy的遍历是采用倒叙的形式,从rootView的子控件开始遍历

例如:rootView包含三个视图,view1,view2,view3,其中view2又包含三个子视图subView1,subView2,subView3则遍历顺序是(本例子前提是所有view的- pointInside:withEvent:方法均返回YES,各个view的布局重叠)

rootView->view3->view2->subView3->subView2->subView1->view1

其中即使父控件符合响应者的要求,同样要遍历子控件寻找最合适的响应者。但是如果父控件不符合响应者要求(pointInside方法返回NO),则子控件不再遍历

2.依赖方法详解

(1)- (BOOL)pointInside:(CGPoint)point  withEvent:(UIEvent *)event;下图是官方文档的解释

返回YES代表点击的point在当前遍历view的范围内

Figure 1-3

(2)- (UIView *)hitTest:(CGPoint)point  withEvent:(UIEvent *)event;下方图片是关于该方法的文档解释

Figure 1-4

简要介绍一下,

      (1)接收到点击事件,开始遍历视图,每个视图的hitTest方法都会调用pointInside:withEvent方法,该方法返回YES则继续执行hitTest方法

      (2)通过override pointInside:withEvent方法让其return NO,则当前视图及其子视图放弃点击事件的处理,交给其父视图完成

     (3)当透明度在0--0.01之间或者hidden属性被赋值YES时,这个方法不再调用

四.代码示例

UIView不能接受传递事件的三种情况

2.事件传递过程

3.用到的方法,使用方式

4.示例

(1)响应链论证

(2)修改响应链

5.Question and Summary

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容