这个函数返回触摸事件发生时,触摸点所在的view。函数执行原理如下
假如用户点击了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。
至此,本次点击事件的第一响应者就通过响应者链的事件分发逻辑成功的找到了。
1.2 响应者链
如果初始化对象(the initial object)——hitTest函数返回的view,或者第一响应者——都没有处理这个事件,UIKit会将事件传递给响应者链上的下一个响应者。每一个响应者对象都可以决定是处理这个事件,还是通过nextResponder函数,将事件传递给响应者链上的下一个响应者。这个过程会一直继续,直到有个一响应者处理这个事件,或者没有任何响应者处理这个事件。
当iOS检测到事件并将它传递给初始化对象时,响应者链就开始了。初始化对象(一般是一个view)是响应者链中第一个有机会对事件进行处理的对象。
下图展示了事件在响应者链上进行分发的两种情况:
下面对左边的情况进行讲解,它的事件传递路径如下
1. initial view尝试处理事件或消息,如果他不能处理,他会将事件或消息传递给他的父视图(superview)
2. superview尝试处理,如果他不能处理,他再将事件或消息传递给他的父视图(superview)
3. 如此进行,直到响应者链的最顶层view(topmost view)决定是否处理,如果topmost view也不处理,则传递给topmost view的view controller
4. view controller尝试处理,如果他也不处理,这传递给window
5. 如果window不处理,则传递给application,即[UIApplication sharedApplication]
6. 如果application也不处理,事件将会被丢弃。
参考:https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/event_delivery_responder_chain/event_delivery_responder_chain.html#//apple_ref/doc/uid/TP40009541-CH4-SW1
http://www.cnblogs.com/snake-hand/p/3178070.html