重新认识响应者链
来源:互联网 发布:淘宝开学季海报 编辑:程序博客网 时间:2024/05/21 19:29
响应者链是对iOS中触摸事件(就是你点击屏幕的时候会产生的事件)的传递的描述。
重点线:1、当一个事件发生后,事件会从父控件传给子控件,也就是说由UIAppdelegate->UIApplication -> UIWindow ->UIViewController-> UIView -> initial view,以上就是事件的传递
2、接下来是事件的响应。首先看initial view能否处理这个事件,如果不能则会将事件传递给其上级视图(inital view的superView);如果上级视图仍然无法处理则会继续往上传递;一直传递到视图控制器view controller,首先判断视图控制器的根视图view是否能处理此事件;如果不能则接着判断该视图控制器能否处理此事件,如果还是不能则继续向上传递;(对于第二个图视图控制器本身还在另一个视图控制器中,则继续交给父视图控制器的根视图,如果根视图不能处理则交给父视图控制器处理);一直到window,如果window还是不能处理此事件则继续交给application处理,如果最后application还是不能处理此事件则将其丢弃
3、在事件的响应中,如果某个控件实现了touches...方法,则这个事件将由该控件来接受,((并且不会继续去沿着响应者链传递了,当然就不会找到第一响应者了))如果调用了[supertouches….];就会将事件顺着响应者链条往上传递,传递给上一个响应者;接着就会调用上一个响应者的touches….方法
1.(1)第一响应者(First responder)指的是当前接受触摸的响应者对象(通常是一个UIView对象),即表示当前该对象正在与用户交互,它是响应者链的开端。整个响应者链和事件分发的使命都是找出第一响应者。(2)第一响应者是系统认为最合适处理事件的控件,如果你触摸了对象,但是如果系统不认为是他最合适,那么也不确定他就会是第一响应者。(3)以上两种说法到底哪种是对的呢?I think the first point is correct.
2.UIWindow对象以消息的形式将事件发送给第一响应者,使其有机会首先处理事件。如果第一响应者没有进行处理,系统就将事件(通过消息)传递给响应者链中的下一个响应者,看看它是否可以进行处理。
从头开始的模拟:
iOS系统检测到手指触摸(Touch)操作时会将其打包成一个UIEvent对象,并放入当前活动Application的事件队列,单例的UIApplication会从事件队列中取出触摸事件并传递给单例的UIWindow来处理,UIWindow对象首先会使用hitTest:withEvent:方法寻找此次Touch操作初始点所在的视图(View),即需要将触摸事件传递给其处理的视图,这个过程称之为hit-test view。
hitTest:withEvent:方法的处理流程如下:
首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内;hitTest:withEvent:调用其他方法
若返回NO,则hitTest:withEvent:返回nil;
若返回YES,则向当前视图的所有子视图(subviews)发送hitTest:withEvent:消息,所有子视图的遍历顺序是从最顶层视图一直到到最底层视图,即从subviews数组的末尾向前遍历,直到有子视图返回非空对象或者全部子视图遍历完毕;
若第一次有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束;
如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)。
如果最终hit-test没有找到第一响应者,或者第一响应者没有处理该事件,则该事件会沿着响应者链向上回溯,如果UIWindow实例和UIApplication实例都不能处理该事件,则该事件会被丢弃;
hitTest:withEvent:方法将会忽略隐藏(hidden=YES)的视图,禁止用户操作(userInteractionEnabled=NO)的视图,以及alpha级别小于0.01(alpha<0.01)的视图。如果一个子视图的区域超过父视图的bound区域(父视图的clipsToBounds 属性为NO,这样超过父视图bound区域的子视图内容也会显示),那么正常情况下对子视图在父视图之外区域的触摸操作不会被识别,因为父视图的pointInside:withEvent:方法会返回NO,这样就不会继续向下遍历子视图了。当然,也可以重写pointInside:withEvent:方法来处理这种情况。
我的问题:找到第一响应者后它不处理事件怎么办?
注意点:一。在controller里面的方法viewDidLoad()里面打印self 的nextResponder显示self的nextResponder为null,但是你延迟打印self.nextResponder就会发现controller(即self)的nextResponder为UIWindow;这说明响应者树的构造过程是在ViewDidLoad周期中来完成的,这个函数会将当前实例的构成的响应者子树合并到我们整个根树中
二。UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的
- 重新认识响应者链
- 重新认识敏子
- 重新认识数据库范式
- 菜鸟-重新认识NTFS
- 重新认识面向对象
- 重新认识js-1
- 重新认识自我
- 震惊!重新认识资本主义。
- 重新认识container
- 重新认识CPU
- 重新认识李小龙
- 重新认识ICE【概览】
- 重新认识fprint,sprint
- 《三国演义》重新认识
- 重新认识C#
- 重新认识控件
- MVC的重新认识
- 重新认识自己
- 桥头客户的作用及如何形成
- python产生随机字符串
- java类加载器
- 在vs2008 C++下调试控制台程序的心得及技巧
- CSDN博客页面自定义左侧博客栏目
- 重新认识响应者链
- Delphi与Windows 7下的用户账户控制(UAC)机制
- Git 使用指南 培养使用Git的好习惯
- hbase安装配置(整合到hadoop)
- Window Styles
- 时间复杂度和空间复杂度
- java实现文件的跨域上传
- 黎活明-3G手机Android应用开发教程含在线支付
- 关键业务系统的JVM启动参数推荐