这篇博文是学习iOS以来的第一篇博文,是对自己学习的一个总结,亦是给大家的一个参考学习,我会尽可能的写得通俗易懂,易于大家理解。
1.iOS中的事件
在iOS中事件大致分为三种:触摸事件,加速计事件,远程控制事件。
2.iOS中的事件,
2.1概念
接下来要讨论一下响应者对象的概念,什么是响应者对象。在iOS中不是任何对象都能处理事件,只有继承了UIResponder得对象才能接受并处理事件,我们称之为“响应者对象”。UIApplication,UIViewController,UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件。
2.2UIResponder
UIResponder内部提供了以下一些方法来处理事件:
2.2.1触摸事件
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event;
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event;
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event;
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event;
2.2.2加速计事件
- (void)motionBegan:(UIEventSubtype)motionwithEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motionwithEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motionwithEvent:(UIEvent *)event;
2.2.3远程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;
2.3接下来说一下我们开发常用的UIView的触摸事件处理
2.3.1UIView是UIResponder的子类,可以覆盖下列4个方法处理不同的触摸事件<Tips:touches中存放的都是UITouch对象>
一根或者多根手指开始触摸view,系统会自动调用view的下面方法
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event;
一根或者多根手指在view上移动,系统会自动调用view的下面方法(随着手指的移动,会持续调用该方法)
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
@property(nonatomic,readonly)NSUInteger tapCount; 记录了触摸事件产生或变化时的时间,单位是秒
@property(nonatomic,readonly)NSTimeInterval timestamp; 当前触摸事件所处的状态
@property(nonatomic,readonly)UITouchPhase phase;
UITouch的方法:
- (CGPoint)locationInView:(UIView*)view;
返回值表示触摸在view上的位置,这里返回的位置是针对view的坐标系的(以view的左上角为原点(0, 0)),
调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
UIEvent属性:
事件类型
@property(nonatomic,readonly)UIEventType type;
@property(nonatomic,readonly)UIEventSubtype subtype;
事件产生的时间
@property(nonatomic,readonly)NSTimeInterval timestamp;
UIEvent方法:
UIEvent还提供了相应的方法可以获得在某个view上面的触摸对象(UITouch)
2.3.2touches和event参数
一次完整的触摸过程,会经历3个状态:
1>不接受用户交互userInteractionEnabled =NO<例如:UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的
>
2>隐藏 hidden = YES
3>透明 alpha = 0.0 ~ 0.01
3.接下来要讨论本文的重点响应者链条
触摸事件处理的详细过程,当用户点击屏幕后产生的一个触摸事件,经过一些列的传递过程后,会找到最合适的视图控件来处理这个事件,找到最合适的视图控件后,就会调用控件的touches方法来作具体的事件处理,touchBegan等等,这些touches方法的默认做法是将事件顺着响应者链条向上传递,将事件交给上一个响应者进行处理,交给上一个相应者进行处理,是指将touches传递给它的父view,一直向上传递。过程顺序 (1)如果view的控制器存在,就传给控制器,如果控制器不存在,则再传递给它的俯视图(2)在试图层次结构的最顶级试图,如果也不能处理收到的事件或消息,则将事件或消息传递给window对象进行处理.(3)如果window也不能进行处理,则将事件或消息传递给UIApplication对象.(4)如果UIApplication也不能进行如理,则将事件和消息丢弃。
接下来为大家做一个Demo,供大家更好的消化。
新建一个工程最中间的黑色view名叫view1,白色view名叫view2,蓝色view名叫view3,他们三个没有class继承关系,只是视图摆放上为继承关系。图1.
三个view视图各自对应自己的试图控制器UIView,
view1对应控制器代码如下图2
view2对应控制器内部代码touchesBegan为空,不做重写。
view3对应控制器内部代码如下图3
按照这样的代码填写运行之后,点击黑色view1,view2,view3,会各自是什么结果呢?大家可以思考一样,做个猜测,再看下面结果是否有出入。
正确结果是这样的:
点击黑色view1变为是红色,点击白色view2变为绿色,点击蓝色view3变为绿色。那么为什么呢?解释一下。
当点击view1的时候,进入view1控制器触摸事件touchBegan:方法,运行到[super touchesBegan:...],会调用父view的touchBegan方法,将事件处理传递给下一个响应者也就是父view2的touchBegan方法,父view2内部这个方法没有重写,不做任何操作改变,如果没有重写操作系统默认会将事件传递给下一个响应者,这里会在传递给view3的控制器touchBegan方法,先执行[super touchesBegan:...](做下提示,这里会再条用下一个响应者的方法,以致window,UIApplication)再执行[[[touchesanyObject]view]setBackgroundColor:[UIColorgreenColor]];执行到这里view1已经变为绿色的了,为什么可以拿到view1呢,因为touches集合类型,内部装的只有一个对象,就是点击的那个view1,先传递给view2控制器,再传递给view3,touches始终装着第一次点击的那个view。变为绿色之后,程序又再执行到view1控制器的第28行,再将view1置为红色,覆盖之前的绿色<友情提示:打上断点测试过程,印象会更清晰>。
点击view2会变为绿色,道理一样,都是传递本view给下一个响应者<也就是view3>,置为绿色,不过这里面view2因为没有重写控制器代码,所以没有覆盖绿色。
点击view3会变为绿色,同上,先执行[super touchesBegan:...],不过执行无实际操作,之后再执行view3代码的第25行,置为绿色。
代码[super touchesBegan:...]和设置操作代码顺序变换,会出现不同的结果,根据实际项目需要而来。例如本例子:如下图2,图3
图2
此时,出现的结果会变为点击三个view1,view2,view3都是绿色。具体原因,执行顺序不同,响应者链的处理过程原理是和上面一致的。
本文讲述的是关于事件处理的知识,其实在iOS3.2之后,苹果又推出的事实识别功能(Gesture Recognizer),在触摸事件处理方面,大大简化了开发者的开发难度,非常好用的功能,不过事件有限,在这里先不多做阐述,以后有时间再写关于手势的博文。如果本文写的有不足之处,请大家谅解也欢迎大家指正,第一篇博文,多多包涵哈@~@