- 发送触摸时间后,系统会将事件添加到系统UIApplication的事件管理队列中
- UIApplication 会在事件队列的最前端取出事件,然后分发下去,通常会把事件分发给KeyWindow处理
- KeyWindow 会在视图层次中 找到一个最合适的视图来处理触摸事件,这也是处理事件过程的第一步
- 找到合适的视图后,就会调用视图控件响应的方法
- 如果父控件不能接受事件,那么子控件就不能接受事件
20170317120911452.png
一个View 是如何判断自己为最佳处理点击事件的View的
// recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; 方法A
// default returns YES if point is in bounds
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; 方法B
对view进行重写这两个方法后,就会发现,点击屏幕后,首先响应的是方法A
如果方法A中,我们没有调用父类的这个方法,那就根据这个方法A的返回view,作为响应事件的View。返回nil ,就是这个View 不响应
如果方法A中 调用了父类的这个方法:[super hitTest:point withEvent:event]; 那这个时候系统就要调用方法B,通过这个方法的返回值,来判断当前这个view能不能响应消息。
如果方法B放回的是No, 那就不用再去遍历它的子视图。方法A 返回的view就是可以响应事件的view。
如果方法B返回的是 YES,那就是遍历它的子视图。(就是上图我们描述的那样,找到合适的view返回,如果找不到,那就由方法A返回的view去响应这个事件。)
//返回一个view来响应事件 (我们如果不想影响系统的事件传递链,在这个方法内,最好调用父类的这个方法)
- (nullableUIView *)hitTest:(CGPoint)point withEvent:(nullableUIEvent *)event
//返回的值可以用来判断是否继续遍历子视图(返回的根据是触摸的point是否在view的frame范围内)
- (BOOL)pointInside:(CGPoint)point withEvent:(nullableUIEvent *)event;