事件分发

在iOS中UIApplication、UIView、UIViewController等继承UIResponder的对象可以响应触摸事件。
事件产生之后,会被加入到由UIApplication管理的事件队列里,接下来自UIApplication往下传递,首先会传递给主window,然后按照view的层级结构一层层往下传递。
规律
UIView :如果view是viewController的根view,那么下一个响应者是viewController,否者是super view
UIViewController 如果viewController的view是window的根view,那么下一个响应者是window;如果viewcontroller是另一个viewcontroller模态推出的,那么下一个响应者是viewcontroller;如果viewcontroller的view被add到另一个viewController的根view上,那么下一个viewcontroller的根view
UIWindow: UIWindow的下一个响应者是UIApplication(一般来说是响应者顶端)
【事件分发】手势识别器
当触摸屏幕产生touch事件后,UIApplication会将事件往下分发,如果视图绑定了手势识别器,touch事件会优先传递给绑定在视图上的手势识别器,如果识别出了手势,就会调用创建手势时所绑定的回调方法,并且会取消touch给所绑定的视图。
UIKit的标准控件(button,选择器。。。)一个view上加了单击手势,一个button,优先button的taget-action事件,不去响应单击事件,如果往button上加单击手势,则响应的是单击手势。
代码判断逻辑:

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event { if (self.userInteractionEnabled == NO|| self.hidden== YES ||self.alpha<=0.01) return nil; //判断触摸点是否在自己范围内 if ([self pointInside:point withEvent:event] == NO) return nil; //遍历所有子视图,查找是否有最合适的视图 for (NSInteger i=self.subviews.count-1; i>=0; i--) { UIView * childView = self.subviews[i]; //转换到子视图坐标系 CGPoint childPoint = [self convertPoint:point toView:childView]; //递归查找是否存在最合适的View UIView *fitView = [childView hitTest:childPoint withEvent:event]; if (fitView) { return fitView; } } return self; }

    推荐阅读