搜索
您的当前位置:首页正文

IOS - 响应者链条

来源:哗拓教育

假如用户点击了View E,下面结合图二介绍hit-test view的流程:
1、A是UIWindow的根视图,因此,UIWindwo对象会首相对A进行hit-test;
2、显然用户点击的范围是在A的范围内,因此, pointInside:withEvent:返回了YES,这时会继续检查A的子视图;
3、这时候会有两个分支,B和C:
点击的范围不再B内,因此B分支的 pointInside:withEvent:返回NO,对应的hitTest:withEvent:返回nil;
点击的范围在C内,即C的 pointInside:withEvent:返回YES;
4、这时候有D和E两个分支:
点击的范围不再D内,因此D 的 pointInside:withEvent:返回NO,对应的hitTest:withEvent:返回nil;
点击的范围在E内,即E的 pointInside:withEvent:返回YES,由于E没有子视图(也可以理解成对E的子视图进行hit-test时返回了nil),因此,E的 hitTest:withEvent:会将E返回,再往回回溯,就是C的 hitTest:withEvent:返回E--->>A的hitTest:withEvent:返回E。
至此,本次点击事件的第一响应者就通过响应者链的事件分发逻辑成功的找到了。
不难看出,这个处理流程有点类似二分搜索的思想,这样能以最快的速度,最精确地定位出能响应触摸事件的UIView。
上面找到了事件的第一响应者,接下来就该沿着寻找第一响应者的相反顺序来处理这个事件,如果UIWindow单例和UIApplication都无法处理这一事件,则该事件会被丢弃。
说明:
1、如果最终 hit-test没有找到第一响应者,或者第一响应者没有处理该事件,则该事件会沿着响应者链向上回溯,如果UIWindow实例和UIApplication实例都不能处理该事件,则该事件会被丢弃;
2、hitTest:withEvent:方法将会忽略隐藏(hidden=YES)的视图,禁止用户操作(userInteractionEnabled=YES)的视图,以及alpha级别小于0.01(alpha<0.01)的视图。如果一个子视图的区域超过父视图的bound区域(父视图的clipsToBounds 属性为NO,这样超过父视图bound区域的子视图内容也会显示),那么正常情况下对子视图在父视图之外区域的触摸操作不会被识别,因为父视图的pointInside:withEvent:方法会返回NO,这样就不会继续向下遍历子视图了。当然,也可以重写pointInside:withEvent:方法来处理这种情况。
3、我们可以重写 hitTest:withEvent:来达到某些特定的目的,下面的链接就是一个有趣的应用举例,当然实际应用中很少用到这些。
Top