乐趣区

关于ios:iOS事件处理-UIResponder

UIResponder是 iOS 中用于解决用户事件的 API,能够解决触摸事件、按压事件 (3D touch)、近程管制事件、硬件静止事件。 能够通过 touchesBeganpressesBeganmotionBeganremoteControlReceivedWithEvent 等办法,获取到对应的回调音讯。
_**UIResponder**不只用来接管事件,还能够解决和传递对应的事件,_如果以后响应者不能解决,则转发给其余适合的响应者解决。

应用程序通过响应者来接管和处理事件,响应者能够是继承自 UIResponder 的任何子类,例如 UIViewUIViewControllerUIApplication 等。当事件来到时,零碎会将事件传递给适合的响应者,并且将其成为第一响应者。

第一响应者未解决的事件,将会在响应者链中进行传递,传递规定由 UIRespondernextResponder决定,能够通过重写该属性来决定传递规定。当一个事件到来时,第一响应者没有接管音讯,则顺着响应者链向后传递。

查找第一响应者

根底 API

查找第一响应者时,有两个十分要害的 API,查找第一响应者就是通过一直调用子视图的这两个API 实现的。

调用办法,获取到被点击的视图,也就是第一响应者。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

hitTest:withEvent: 办法外部会通过调用这个办法,来判断点击区域是否在视图上,是则返回YES,不是则返回NO

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

查找第一响应者

应用程序接管到事件后,将事件交给 keyWindow 并转发给根视图,根视图依照视图层级逐级遍历子视图,并且遍历的过程中一直判断视图范畴,并最终找到第一响应者。

keyWindow 开始,向前逐级遍历子视图,一直调用 UIViewhitTest:withEvent:办法,通过该办法查找在点击区域中的视图后,并持续调用返回视图的子视图的 hitTest:withEvent: 办法,以此类推。如果子视图不在点击区域或没有子视图,则以后视图就是第一响应者。

hitTest:withEvent: 办法中,会从上到下遍历子视图,并调用 subViewspointInside:withEvent:办法,来找到点击区域内且最下面的子视图。如果找到子视图则调用其 hitTest:withEvent: 办法,并继续执行这个流程,以此类推。如果子视图不在点击区域内,则疏忽这个视图及其子视图,持续遍历其余视图。

能够通过重写对应的办法,管制这个遍历过程。通过重写 pointInside:withEvent: 办法,来做本人的判断并返回 YESNO,返回点击区域是否在视图上。通过重写 hitTest:withEvent: 办法,返回被点击的视图。

此办法在遍历视图时,疏忽以下三种状况的视图,如果视图具备以下特色则疏忽。然而视图的背景色彩是clearColor,并不在疏忽范畴内。

  1. 视图的 hidden 等于 YES。
  2. 视图的 alpha 小于等于 0.01。
  3. 视图的 userInteractionEnabled 为 NO。

如果点击事件是产生在视图外,但在其子视图外部,子视图也不能接管事件并成为第一响应者。这是因为在其父视图进行 hitTest:withEvent: 的过程中,就会将其疏忽掉。

作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是一个我的 iOS 交换群:642363427 不论你是小白还是大牛欢送入驻,分享 BAT, 阿里面试题、面试教训,探讨技术,大家一起交流学习成长!

事件传递

传递过程

  1. UIApplication接管到事件,将事件传递给keyWindow
  2. keyWindow遍历 subViewshitTest:withEvent:办法,找到点击区域内适合的视图来处理事件。
  3. UIView的子视图也会遍历其 subViewshitTest:withEvent:办法,以此类推。
  4. 直到找到点击区域内,且处于最上方的视图,将视图逐渐返回给UIApplication
  5. 在查找第一响应者的过程中,曾经造成了一个响应者链。
  6. 应用程序会先调用第一响应者处理事件。
  7. 如果第一响应者不能处理事件,则调用其 nextResponder 办法,始终找响应者链中能解决该事件的对象。
  8. 最初到 UIApplication 后依然没有能解决该事件的对象,则该事件被废除。
退出移动版