iOS中的事件
1.事件的生命周期
事件的生命周期从事件的产生和传递(事件如何从父控件传递到子控件并寻找到最合适的view、寻找最合适的view的底层实现、拦截事件的处理)->事件的响应(找到最合适的view后对事件进行处理,touches方法的重写)
2.事件的分类
iOS中的事件可以分为3大类型:
- 触屏事件(例如点击按钮、通过手势缩放图片、拖动上下滚动页面等)
- 传感器事件(例如摇一摇红包、通过旋转设备控制赛车方向、指南针等)
- 远程控制事件(例如耳机的线控、外接手柄、遥控器等)
3.响应者对象(UIResponder)
在iOS中只有继承了UIResponder的对象才能接收和处理事件,UIResponder的子类包括UIView,UIViewController,UIApplication等。响应者接收到原始事件数据,必须处理事件转发到另一个响应者对象,当APP接收到一个事件事,UIKit自动引导事件到最合适的的响应者对象,也叫做第一响应者。
UIResponder内部提供了以下方法来处理事件
触摸事件
- (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;
加速计事件
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
远程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;
4.事件中的概念
在自定义UIView为属性的控件时可以重写触摸事件的方法来进行点击回调。在回调中可以看到方法接收两个参数,一个是UITouch对象的集合,还有一个是UIEvent对象。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"触摸开始--touches:%@,event:%@",touches,event);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"开始移动--touches:%@,event:%@",touches,event);
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"触摸结束--touches:%@,event:%@",touches,event);
}
//只有在程序强制退出或者来电时才会调用
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"触摸取消--touches:%@,event:%@",touches,event);
}
4.1UIEvent
表示用户交互的事件对象,每产生一个事件,就会产生一个UIEvent对象。在一个用户点击事件处理过程中,UIEvent对象是唯一的。
UIEvent属性如下:
//事件类型
@property(nonatomic,readonly) UIEventType type NS_AVAILABLE_IOS(3_0);
@property(nonatomic,readonly) UIEventSubtype subtype NS_AVAILABLE_IOS(3_0);
//事件产生时间
@property(nonatomic,readonly) NSTimeInterval timestamp;
4.2UITouch
当用户用一根手指触摸屏幕时,会创建一个与手指相关的UITouch对象 ,一根手指对应一个UITouch对象。
UITouch属性如下:
//触摸产生时所处的窗口
@property(nonatomic,readonly,retain) UIWindow *window;
//触摸产生时所处的视图
@property(nonatomic,readonly,retain) UIView *view
;
//短时间内点按屏幕的次数,可以根据tapCount判断单击、双击或更多的点击
@property(nonatomic,readonly) NSUInteger tapCount;
//记录了触摸事件产生或变化时的时间,单位是秒
@property(nonatomic,readonly) NSTimeInterval timestamp;
//当前触摸事件所处的状态
@property(nonatomic,readonly) UITouchPhase phase;
UITouch方法如下:
// 返回值表示触摸在view上的位置
// 这里返回的位置是针对view的坐标系的(以view的左上角为原点(0, 0))
// 调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
(CGPoint)locationInView:(UIView *)view;
// 该方法记录了前一个触摸点的位置
(CGPoint)previousLocationInView:(UIView *)view;
事件的传递和响应
1.事件的产生和传递
1.1事件的产生
1.发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的队列事件中
2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会先发送事件给应用程序的主窗口(keyWindow)
3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件
1.2事件的传递
触摸事件的传递是从父控件传递到子控件。事件传递给窗口或者控件后,就调用hitTest:withEvent:
方法寻找更合适的view。方法底层会调用pointInside:withEvent:
方法判断点在不在方法调用者的坐标系上,如果返回YES说明点在当前view上,继续通过hitTest:withEvent:
方法遍历子控件,直到找到最合适的view。如返回NO,代表事件不在view内,直接返回nil,说明当前view不是最合适的view,其以下的子控件也都会被忽略。
这个方法会忽略以下情况:
- 视图是隐藏的 hidden = YES
- 用户交互是关闭的 userInteractionEnabled = NO
- 透明度小于0.01的 alpha < 0.01
2.事件的响应
- 响应者链条
在ios程序中每个控件的摆放是有前后关系的,这种先后关系构成的一个链条就叫响应者链。 - 响应者链的事件传递过程
1.如果当前view是控制器的view,那么控制器就是上一个响应者,事件就传递给控制器;如果当前view不是控制器的view,那么父视图就是当前view的上一个响应者,事件就传递给它的父视图
2.在视图层次结构的最顶级视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给window对象进行处理
3.如果window对象也不处理,则其将事件或消息传递给UIApplication对象
4.如果UIApplication也不能处理该事件或消息,则将其丢弃
网友评论