响应链是什么,响应链是由响应者(Responder object)之间的touch消息传递以及检测组成,我们也可以理解为响应链是由响应者组成。
在开发过程中我们所关注的是,在屏幕上点击后,这个点击该由哪个对象来响应以及对象是怎么样接受到这个点击事件的。
在理解响应链的时候,我们要先了解下hit-test view,从表面意思可以看出就是接受点击测试的视图。在发生一个点击事件的时候,UIApplication对象会从队列的顶部获取到这个事件,在把这个事件分配给可以处理这个事件的视图。 事件会由一个指定的途径传递,一直到事件可以响应,如果响应链走了一遍,没有发现可以接收事件的视图,那么该事件就会被丢弃。如果有视图可以响应这个事件,这个视图就是hit-test view,发现hit-test view的这个过程称为hit-testing.
在开发中我们,可能会用到下面这2个函数
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
这个是用来当前在view hierarchy中的view是否包含指定的点。
这个函数一般情况下很少直接调用,一般都是重写这个方法来处理视图中子视图的touch事件。如果你重写了这个函数,那么就要注意了,你设置view的user interactions,hidden,alpha,对于他是不起作用的,就是不管你怎么设置,这个函数都会一直进入。所以这是个蛋疼的地方,使用的时候要切记这个,不然你会有惊喜的。
另外你添加了子视图,但是clipsToBounds是NO的情况下,当你点击子视图超出view的部分,是不会响应的,点击区域只有在view的bounds中才会响应的。这也是要注意的。
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
这个函数返回bool值,来反映当前point是否在view中。通常都是在上面- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event的函数调用此方法。
上面2个函数一般情况下,使用的不多,除非是特殊情况下(变态的需求)才会使用。
接下来来说下当一个touch事件发生后,hit-testing是如果检测到哪个视图响应的。
hit-testing在检测hit-test view的时候,会遍历view的所有子视图来判断是哪个视图包含当前的点击点。一旦检测到hit-test view,就会传递touch事件给视图去处理。
下面通过一个例子来详细看下。
在上面的图片中,如果touch点击的时候,是点击在view E里面。则检测过程是
1.首先是touch点在view A的bounds中,接下来检测view B和view C.
2.检测到touch点不在view B,在view C中,接下来检测view D和view E.
3.检测到touch点不在view D中,在view E中。
此时hit-testing过程已经完成,view E就是hit-test View.
检测到hit-test View后,此view拥有优先处理事件的权利,如果view不能处理这个事件,事件就会沿着响应者链向下传递,直到找到一个能处理该事件的view.
那这个传递过程是怎么样的呢,我们就要知道The Responder Chain的组成了,在开头的时候已经说了(个人理解)。
下面给个确切的定义(from apple document):The responder chain is a series of linked responder objects。
响应链的起始点是,hit-test view(起点)和UIApplication对象(终点)。
下面来看下响应链的具体传递
可以看出,传递的方向就是从最上面的view向下传递,如果view是view controller的view,还会经过view controller之后在向下传递,最终到达app对象。