窥探事件响应机制

题外话: 编程还是要多和身边的朋友一起交流,交流创造灵感,交流创造价值。

问题讨论

一个北京的朋友准备来杭州发展,先暂时住到我这里。他问了我一个问题:

iOS系统对使用手势的事件监听和普通的 event touch 事件监听响应机制到底有何不同?

本来自认为对 iOS 的事件响应机制非常了解的我,一下子就懵逼了。平时也只考虑过当屏幕有事件产生,到确定最合适的 view ,再到 application 对 event 进行分发,然后由响应者链条传递事件,最后由最合适的 view 来执行响应事件的方法。这一过程我相信凡是有 iOS 开发基础的人都再熟悉不过。

我从来没考虑过将事件处理和手势联系起来考虑。实践是检验真理的唯一标准,于是我尝试给一个 view 添加手势,并且触发其 touch began 方法。

发现两个方法都被调用了。

于是我们一起查经阅典:UIKit 界面架构

图片引用自 kenshincui 的博客

发现 UIGestureRecognizer 和 UIResponder 并没有关系,实际他们也是没有关系的。

UIResponder 和 事件监听响应机制

对于基础知识,大家可以参考我博客中的这篇文章:事件处理

这里简单通过函数调用栈来讲解一下事件的产生,和事件分发处理的过程。如果在 view 中的hitTest:withEvent: 方法中打个断点,AppDelegate 的 touch begin 方法中打个断点,点击 view 时我们会发现:

通过函数调用栈,可以很清楚的看出,事件的产生,和通过调用 hitTest:withEvent: 方法来确定最合适的 响应事件的 view ,从 window 开始寻找。会有一个递归操作不断的调用子类的 hitTest:withEvent: 方法确定最合适的 view。

通过 touch begin 方法的调用栈可以看出,在确定最合适的 view 后,Application 会通过 sendEvent:方法分发事件,一直到最合适的 view ,然后调用其 touch方法。如果我们实现了 touch 方法,则会按照我们的实现走,如果没有实现,则默认调用 super 的 touch 方法,一直到 appDelegate 的 touch 方法,最后事件被释放掉。

OK,现在复习了一遍事件传递响应机制后。我们来看看手势是如何来实现这个事件的监听和响应的。

UIGestureRecognizer 的 事件传递响应机制

在给 view 添加手势后,在 view 内部的 hitTest:withEvent: 方法打了断点,发现其方法调用栈和上面第一张图是一样的,这说明手势和touch 底层共用 一套 触摸产生事件和寻找最合适执行响应的 view 的机制。

在手势响应的同时,UIResponser 的 touch begin方法仍然被调用,只是没有去实现它,从而被 Application将事件释放掉了。

我们查看函数调用栈:

可以看出,其事件的传递和派发也是相同的,只是在响应的时候,系统应该是先调用 touch begin 方法响应,如果检测出 view 是有手势监听,则将 event 对象也传递给了手势,然后调用手势 的 action 进行响应。

主要的思路清晰后,下面来讨论一些细节问题。

一些细节问题(以下结论都被验证过)

  1. 如果父控件和子控件都添加了手势,点击子控件,则父控件的手势 action方法 不会调用。
  2. 如果子控件没有添加手势,而父控件添加了手势,点击子控件,则父控件的手势 action 方法 会被调用。

也就是说 系统 在处理手势响应事件上和 touch begin 的事件响应机制是比较类似的。但需要注意的是,他们是毫无关联的。

以上手势的响应完全不会影响 touch begin 的函数调用。就像触摸屏幕产生事件后,手势和touch 都会通过hitText 方法找到最合适的 view ,并且由 application 对象分发传递 event,然而如果有添加手势,则将 event 对象传递给最合适的 view 调用其 UIResponser 方法的同时,也会将 event 对象传递给 UIGestureRecognizer 并调用其对应的 响应方法。 他们是互不影响的。

最后要说的是:编程要和朋友一起才快乐!

文章作者: Ammar
文章链接: http://lizhaoloveit.cn/2016/08/12/%E7%AA%A5%E6%8E%A2%E4%BA%8B%E4%BB%B6%E5%93%8D%E5%BA%94%E6%9C%BA%E5%88%B6/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ammar's Blog
打赏
  • 微信
  • 支付宝

评论