ios responder响应者链,事件传递规则
当我们手指点击屏幕时,iphone os会用点击的信息和类型生成一个UIEvent对象放入应用程序的事件队列中。然后UIApplication单例对象从队列中顶部取出,调用当前窗口UIWindow对象的hitTest:withEvent:方法, 看看当前点击的点是不是在window内, 如果是则逆序遍历(后加载的先遍历,因为后加载才最靠前front,这样优化了查找效率)subview的hitTest:withEvent:方法,如果其中一个subview的hitTest:withEvent:方法返回了接收事件UIView,那么就不会继续传递给剩下的其他subview。
hitTest:withEvent:方法的内部实现如下:
hitTest:withEvent:注:hitTest内部主要是一个pointInside:withEvent:方法,该方法和hitTest一样都是UIView的方法,通过该方法可以判断point是否落在view的bound范围内
hitTest寻找响应View的路径:
UIApplication分发事件(sendEvent方法)->UIWindow->View(rootController的View)->Subview(有可能childViewController的view)->Subview->Subview........ 直到找到响应view为止。
touch响应方法:
当通过hitTest找到响应View之后,就会调用该View(继承UIResponder)的下列方法
touch 响应事件官方文档里面解释了这几个方法,the default implementation of this method forwards the message up the responder chain. 意思就是这些方法的默认实现是把touch事件通过响应者链进行传递
响应者链:
view(之前通过hitTest找到的相应view)->superView->...->UIViewController的view->UIViewController->ParentController的view->parentController->...->RootController的view->RootController->UIWindow->UIApplication->AppDelegate
那么一个UIResponder是如何将事件传递给响应者链的下一个对象的呢,其实靠的是UIResponder的一个只读属性串联起来的,如下图
UIResponder next属性当一个view被addSubview到superView时,view的next就指向superView, UIViewController的View的next指向viewController, 而UIViewController的next指向parentController的View,如果是rootViewController那么next指向UIWindow