IOS事件处理
概述
事件
一个事件即由硬件捕捉并产生的一个表示用户操作设备的对象并发送给IOS——例如:一个手指点击屏幕或摇动设备。许多event都是UIKit框架中UIEvent类的实例。UIEvent对象可能封装了用户事件所关联的状态, 像关联的点击。UIEvent对象同时也记录了事件所产生的时刻。当一个用户事件发生时——例如,当手指点击屏幕并在其上移动——IOS连续发送事件对象给应用程序进行处理。
view ui框架 UIKit当前可识别三种类型的事件:点击事件,摇动事件及远程控制事件。UIEvent类对其定义了enum常量:
typedef enum {
UIEventTypeTouches,
UIEventTypeMotion,
UIEventTypeRemoteControl
} UIEventType;
typedef enum {
UIEventSubtypeNone = 0,
UIEventSubtypeMotionShake = 1,
UIEventSubtypeRemoteControlPlay = 100,
UIEventSubtypeRemoteControlPause = 101,
UIEventSubtypeRemoteControlStop = 102,
UIEventSubtypeRemoteControlTogglePlayPause = 103,
UIEventSubtypeRemoteControlNextTrack = 104,
UIEventSubtypeRemoteControlPreviousTrack = 105,
UIEventSubtypeRemoteControlBeginSeekingBackward = 106,
UIEventSubtypeRemoteControlEndSeekingBackward = 107,
UIEventSubtypeRemoteControlBeginSeekingForward = 108,
UIEventSubtypeRemoteControlEndSeekingForward = 109
} UIEventSubtype;
每个事件都有其对应的事件类型和子事件类型,它们可以由UIEvent对象的type和subtype属性进行访问。事件类型包括点击事件,摇动事件及远程控制事件。在IOS3.0中,包括了摇动子事件类型(UIEventSubtypeMotionShake)及多种远程控制子事件类型;点击事件所对应的子事件类型为UIEventSubtypeNone。
你不应该在你代码中retain一个UIEvent对象。如果你需要保留一个事件对象的当前状态为以后进行处理,你应该通过合适的方法(使用实例变量或字典对象)拷贝或保存状态值。
事件传递
从事件发生到其处理的对象,传递要经过相当长及特殊的一段过程。当用户点击设备屏幕时,IOS捕捉到一系列的触摸,将其打包到UIEvent对象中并放置到应用程序活动事件队列中。如果系统检测到摇动设置为一个有效的移动事件,则也将其打包并放置到应用程序活动事件队列中。单例UIApplication对象管理应用程序,从事件队列中取出最前面的事件并将其分发以便处理。通常,其发送事件给应用程序的主窗口——即聚焦于用户交互的窗口——窗口对象代表窗口再发送事件给初始对象进行处理。初始对象对于点击事件和摇动事件是不相同的。
点击事件。窗口对象使用hit-testing及响应者链表去到对该事件响应的视图。在hit-testing中,窗口到视图继承树中最上层的视图并调用hitTest:withEvent:方法;该方法递归调用视图继承树中每个视图的pointInSide:withEvent:方法并在其返回true后,从该视图开始沿着继承树向下,直到到一个点击事件在其范围之内的子视图。该子视图即为hit-test视图。
如果该hit-test视图无法处理该事件,则事件沿着响应者链表进行传递直至到能处理该事
件的视图。一个点击对象在其生命周期中一直与hit-test视图相关联,即使点击对象移动到一样该视图之外(?)。
摇动及远程控制事件。窗口对象发送每个摇动及远程控制事件给首响应者进行处理。
尽管hit-test视图和首响应者通常是同一个视图对象,但它们并不总是相同。
UIApplication对象及每个UIWindow对象在sendEvent:方法中进行事件传递,因为这些方法是从应用程序传递来事件的汇集点,所以你可以继承UIApplication或UIWindow并重载sendEvent:方法来监控事件(只有少量的应用程序需要此实现)。如果你重载了该方法,请确保调用了超类的sendEvent:方法。无论如何都不要篡改事件的分发。
响应对象和响应者链
前面的讨论已涉及到响应者的概念。那什么是响应者及它是如何适应消息分发的框架呢?
响应者对象是一个能接收并处理事件的对象。UIResponser是所有响应者对象对的基类,另一个熟悉并简单的名字为响应者。该基类定义了一系列编程接口,不但为事件处理进行服务而且还提供了通用的响应行为处理。UIApplication, UIView及所有作为UIView子类的UIKit类(包括UIWindow)都直接及间接的继承自UIResponser,所有的这些类的实例都是响应者对象。
首响应者是应用程序的一个响应者对象(通常为UIView)作为接收除点击事件以外其它事件的首个响应对象。UIWindow对象通过消息发送摇动或远程控制事件给首响应者,让其对事件进行优先处理。为了能接收到UIWindow对象发送来的消息,响应者对象必需申明canBecomeFirstResponser方法并返回Yes;并能接收到becomeFirstResponser消息(该方法可以在对象内部进行调用)。首响应者是Window中的第一个视图用以接收以下的事件或消息:
摇动事件——通过调用UIResponser的摇动处理方法
远程控制事件——通过调用UIResponser的remoteControlReceivedWithEvent方法
操作消息——当用户操作了Control(像按钮或滑块)便没有指定消息的接收者
Editing-Menu Message
首响应者也在文字编辑中扮演作用。当对Text View或Text Field聚焦进行输入时即成为了首响应者,并促使了虚拟键盘的出现。
注:应用程序必需显式的为摇动,远程控制事件及editing-menu消息处理设置首响应者,当用户点击Text View或Text Field时,UIKit自动将其设置为首响应者。
如果首响应者或hit-test视图不处理收到的消息,UIkit则通过消息的形式将事件转发到响应者链的下一个响应者,看其是否能过该消息进行处理。
响应者链是一系列已连接的响应者对象,事件或消息在其路径上进行传递。在其上允许响应者将事件处理的责任传递给高层的其它响应者。应用程序根据响应者的处理能力将事件向上进行传递。因为hit-test视图是一个响应者对象,当应用程序接收到点击事件时可能会对其进行更进一步的处理。响应者链包括一系列的下一个响应者(每一个通过nextResponser方法返回)。如下图所示。
当系统转发了一个点击事件,首先将其发送给特殊的视图。对于点击事件,这个特殊视图为调用hitTest:withEvent方法所返回的视图;对于它事件或消息,该特殊视图即为首响应者。如果首个视图无法处理收到的事件,则其通过在响应者链中的特殊路径向上传递。
1. hit-test视图或首响应者发送事件或消息给其对应的视图控制器,如果该控制器存在;如果控制器不存在,则将其传递给它的父视图
2. 如果视图或它的控制器无法处理收到的事件或消息,则将其传递给该视图的父视图
3. 每一个在视图继承树中的上层视图如果不能处理收到的事件或消息,则重复上面的步骤1,
2
4. 在视图继承树的最上层视图,如果也不能处理收到的事件或消息,则其将事件或消息传递给窗口对象进行处理
5. 如果窗口对象也不能进行处理,则其将事件或消息传递给UIApplication对象
6. 如果UIApplication也不能处理该事件或消息,则将其丢弃
如果你有自定义的处理摇动,远程控制事件或其它消息的视图,你不应该将事件或消息直接发送到响应者链的下一个响应者。取代方法是调用父类的当前事件处理方法,让UIKit对消息传递进行处理。
多点触摸事件
触摸事件在IOS中是基于多点触摸模型。取代鼠标和键盘,用户通过触摸设备的屏幕来操作对象,输入数据以及实现其它意愿。IOS识别的一个或多个手指对屏幕进行触摸并将其作为多点触摸序列的一部分。该序列以用户第一个手指触摸屏幕开始一直持续到最后一个手指
离开屏幕。IOS通过触摸序列来跟踪手指在屏幕上的移动并记录它们的特征,包括手指在屏幕上的位置以及触摸发生的时间。应用程序通常会识别一组触摸为一个手势并对其进行相应的响应,例如:放大缩小屏幕内容用于响应pinch手势,对屏幕内容进行滚动用于响应flick手势。
UIKit中许多类对于多点触摸的处理有别于其对象。对于UIControl类的子类则特别如此,像UIButton和UISlider。对于从UIControl继承的对象通常称为控制对象,它们期望收到特定的手势,像点击或向某方向进行拖动。通过适应的配置,当手势发生时它们会发送操作消息给目标对象。其它的UIkit类以不同的方式对手势进行响应,以ScrollView为例,为表视图,文本视图以及其它有大块内容区域视图提供滚动行为。
有些应用程序不需要直接响应事件,它们信赖于UIkit类所提供的行为。如果你创建了一个UIView的子类并且希望该视图对触摸进行响应,你就必须为处理触摸事件而编写代码。如果你希望UIKit中的对象对于事件有不同的响应,你就必须对UIkit中使用到的该类进行继承并重载合适的事件处理方法。
事件和触摸
在IOS中,触摸表示手指在屏幕上的接触或移动并作为唯一多点触摸序列的一部分。例如:挤(pinch-close)手势有两个触摸:两个手指在屏幕上以相反的方向向对方移动。同时也有一个手指操作的简单手势,例如:单击,双击,拖动和滑动(flick)。应用程序也有可能处理复杂的手势。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论