项目中遇到了这个问题(collection添加手势后不响应点击事件),虽然已经有了两种解决方案,但是有点不满足,之前对事件链早有耳闻,想想有没有办法通过这种方式来解决。
ps:写这篇文章的时候还未解决问题,目的是为了把学到的知识先整理起来,要不然问题解决之后把原理忘了就得不偿失
参考文章: 史上最详细的iOS之事件的传递和响应机制-原理篇,一篇很好的参考资料
事件的传递:通过hit-test方式传递给子视图 手指触碰屏幕,由UIApplication->window->处理事件最适合的view 证明:
[self.view addSubview:cyan];
[cyan addSubview:puple];
[puple addSubview:btn];
//每个view都重写hitTest方法
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
NSLog(@"%s\t%d", __func__, __LINE__);
UIView *view = [super hitTest:point withEvent:event];
NSLog(@"last %s\t%d", __func__, __LINE__);
return view;
}
点击橙色按钮

-[cyanView hitTest:withEvent:] 16
-[purpleView hitTest:withEvent:] 15
-[ShapeButton hitTest:withEvent:] 30
last -[ShapeButton hitTest:withEvent:] 36
last -[purpleView hitTest:withEvent:] 19
last -[cyanView hitTest:withEvent:] 20
-[cyanView hitTest:withEvent:] 16
-[purpleView hitTest:withEvent:] 15
-[ShapeButton hitTest:withEvent:] 30
last -[ShapeButton hitTest:withEvent:] 36
last -[purpleView hitTest:withEvent:] 19
last -[cyanView hitTest:withEvent:] 20
点击事件
结论:
从父视图传递到子视图,当父视图不能接受触摸事件(例如:alpha<0.01...)时,子视图也不能接受点击事件
hit-test方法会不断调用,子view的hit-test方法,当子view有返回值之后才会返回父view的hit-test返回值
有些人以为hit-test是事件链,官方文档也有这样的解释
Returns the farthest descendant of the receiver in the view hierarchy (including itself) that contains a specified point.
返回包含指定点的视图层次结构(包括自身)中接收器的最远的后代。
我认为,hit-test不光包含事件链还包括响应链, hit-test方法本身会调用子类的hit-test方法,由父view向子view传递hit-test方法,这叫做事件链. 在hit-test方法中,如果有view响应就继续向子view的hit-test传递,如果没有则返回nil,最后返回的view就是需要做出响应的那个view,然后父view返回自身。这是一个循环
这个也就对应了上面hit-test方法为什么会走两次.