IOS事件处理机制(关于触发者和响应者的确认)

事件处理机制

在iOS中发生触摸后,事件会加入到UIApplication事件队列(在这个系列关于iOS开发的第一篇文章中咱们分析iOS程序原理的时候就说过程序运行后UIApplication会循环监听用户操做),UIApplication会从事件队列取出最前面的事件并分发处理,一般先分发给应用程序主窗口,主窗口会调用hitTest:withEvent:方法(假设称为方法A,注意这是UIView的方法),查找合适的事件触发视图(这里一般称为“hit-test view”):html

  1. 在顶级视图(key window的视图)上调用pointInside:withEvent:方法判断触摸点是否在当前视图内;
  2. 若是返回NO,那么A返回nil;
  3. 若是返回YES,那么它会向当前视图的全部子视图(key window的子视图)发送hitTest:withEvent:消息,遍历全部子视图的顺序是从subviews数组的末尾向前遍历(从界面最上方开始向下遍历)。
  4. 若是有subview的hitTest:withEvent:返回非空对象则A返回此对象,处理结束(注意这个过程,子视图也是根据pointInside:withEvent:的返回值来肯定是返回空仍是当前子视图对象的。而且这个过程当中若是子视图的hidden=YES、userInteractionEnabled=NO或者alpha小于0.1都会并忽略);
  5. 若是全部subview遍历结束仍然没有返回非空对象,则A返回顶级视图;

上面的步骤就是点击检测的过程,其实就是查找事件触发者的过程。触摸对象并不是就是事件的响应者(例如上面第一个例子中没有重写KCImage触摸事件时,KCImge做为触摸对象,可是事件响应者倒是UIViewController),检测到了触摸的对象以后,事件究竟是如何响应呢?这个过程就必须引入一个新的概念“响应者链”。数组

什么是响应者链呢?咱们知道在iOS程序中不管是最后面的UIWindow仍是最前面的某个按钮,它们的摆放是有先后关系的,一个控件能够放到另外一个控件上面或下面,那么用户点击某个控件时是触发上面的控件仍是下面的控件呢,这种前后关系构成一个链条就叫“响应者链”。在iOS中响应者链的关系能够用下图表示:app

iOS_responder_chain_2x

当一个事件发生后首先看initial view可否处理这个事件,若是不能则会将事件传递给其上级视图(inital view的superView);若是上级视图仍然没法处理则会继续往上传递;一直传递到视图控制器view controller,首先判断视图控制器的根视图view是否能处理此事件;若是不能则接着判断该视图控制器可否处理此事件,若是仍是不能则继续向上传递;(对于第二个图视图控制器自己还在另外一个视图控制器中,则继续交给父视图控制器的根视图,若是根视图不能处理则交给父视图控制器处理);一直到window,若是window仍是不能处理此事件则继续交给application(UIApplication单例对象)处理,若是最后application仍是不能处理此事件则将其丢弃。ide

这个过程你们理解起来并不难,关键问题是在这个过程当中各个对象如何知道本身能不能处理该事件呢?对于继承UIResponder的对象,其不能处理事件有几个条件:ui

  • userInteractionEnabled=NO 
  • hidden=YES 
  • alpha=0~0.01 
  • 没有实现开始触摸方法(注意是touchesBegan:withEvent:而不是移动和结束触摸事件)

固然前三点都是针对UIView控件或其子控件而言的,第四点能够针对UIView也能够针对视图控制器等其余UIResponder子类。对于第四种状况这里再次强调是对象中重写了开始触摸方法,则会处理这个事件,若是仅仅写了移动、中止触摸或取消触摸事件(或者这三个事件都重写了)没有写开始触摸事件,则此事件该对象不会进行处理。htm

相信到了这里你们对于上面点击图片为何不能拖拽已经很明确了。事实上经过前面的解释你们应该能够猜到即便KCImage实现了开始拖拽方法,若是在KCTouchEventViewController中设置KCImage对象的userInteractionEnabled为NO也是能够拖拽的。对象

 

转自:崔江涛 http://www.cnblogs.com/kenshincui/p/3950646.html#remoteControl  很是感谢博主的详细介绍blog

相关文章
相关标签/搜索