iOS 触摸事件

事件类型

在iOS系统中,一共有三种形式的事件:触摸事件(Touch Event),运动事件(Motion Event)和远端控制事件(Remote-control Event)。顾名思义,触摸事件就是当用户触摸屏幕时发生的事件,而运动事件是用户移动设备时发生的事件:加速计,重力感应。远端控制事件可能比较陌生:如通过耳机进行控制iOS设备声音等都属于远端控制事件。

iOS处理触屏事件,分为两种方式。高级事件处理,利用UIKit提供的各种用户控件或者手势识别器来处理事件。低级事件处理,在UIView的子类中重写触屏回调方法,直接处理触屏事件。

触摸事件

UIEvent: iOS将触摸事件定义为第一个手指开始触摸屏幕到最后一个手指离开屏幕定义为一个触摸事件。用类UIEvent表示。

UIEvent的作用:一次完整的触摸过程中,只会产生一个事件对象,4个触摸方法都是同一个event参数,如果两根手指同时触摸一个view,那么view只会调用一次touchesBegan:withEvent:方法,touches参数中装着2个UITouch对象,如果这两根手指一前一后分开触摸同一个view,那么view会分别调用2次touchesBegan:withEvent:方法,并且每次调用时的touches参数中只包含一个UITouch对象,根据touches中UITouch的个数可以判断出是单点触摸还是多点触摸。

UITouch: 一个手指第一次点击屏,会形成一个UITouch对象,直到离开销毁。表示触碰。UITouch对象能表明了当前手指触碰的屏幕位置,状态。状态分为开始触碰、移动、离开。

UITouch的作用: 当用户用一根手指触摸屏幕时,会创建一个与手指相关联的UITouch对象,一根手指对应一个UITouch对象,保存着跟手指相关的信息,比如触摸的位置、时间、阶段,当手指移动时,系统会更新同一个UITouch对象,使之能够一直保存该手指在的触摸位置,当手指离开屏幕时,系统会销毁相应的UITouch对象。

在屏幕上的每一次动作事件都是一次Touch,在iOS中用UITouch对象表示每一次的触控,多个Touch组成一次Event,用UIEvent来表示一次事件对象。UIEvent实际包括了多个UITouch对象。有几个手指触碰,就会有几个UITouch对象。

UIView的触摸事件函数

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event; // 一根或者多根手指开始触摸view,系统会自动调用view的下面方法

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event; // 一根或者多根手指在view上移动,系统会自动调用view的下面方法(随着手指的移动,会持续调用该方法)

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event; // 一根或者多根手指离开view,系统会自动调用view的下面方法

- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event; // 触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程,系统会自动调用view的下面方法

提示:touches中存放的都是UITouch对象

响应链

响应者对象(UIResponder)

UIResponser就是用来接收和处理事件的类,先抛开iOS中的具体传递细节,系统发送UIEvent的Touch message给UIResponser类。UIResponser提供了一下几个函数来做事件处理

//触摸事件- (void)touchesBegan:(NSSet *)touches withEvent:(nullableUIEvent*)event;- (void)touchesMoved:(NSSet *)touches withEvent:(nullableUIEvent*)event;- (void)touchesEnded:(NSSet *)touches withEvent:(nullableUIEvent*)event;- (void)touchesCancelled:(NSSet *)touches withEvent:(nullableUIEvent*)event;- (void)touchesEstimatedPropertiesUpdated:(NSSet *)touchesNS_AVAILABLE_IOS(9_1);//物理按钮,遥控器上面的按钮在按压状态等状态下的回调- (void)pressesBegan:(NSSet *)presses withEvent:(nullableUIPressesEvent*)eventNS_AVAILABLE_IOS(9_0);- (void)pressesChanged:(NSSet *)presses withEvent:(nullableUIPressesEvent*)eventNS_AVAILABLE_IOS(9_0);- (void)pressesEnded:(NSSet *)presses withEvent:(nullableUIPressesEvent*)eventNS_AVAILABLE_IOS(9_0);- (void)pressesCancelled:(NSSet *)presses withEvent:(nullableUIPressesEvent*)eventNS_AVAILABLE_IOS(9_0);//设备的陀螺仪和加速传感器使用- (void)motionBegan:(UIEventSubtype)motion withEvent:(nullableUIEvent*)eventNS_AVAILABLE_IOS(3_0);- (void)motionEnded:(UIEventSubtype)motion withEvent:(nullableUIEvent*)eventNS_AVAILABLE_IOS(3_0);- (void)motionCancelled:(UIEventSubtype)motion withEvent:(nullableUIEvent*)eventNS_AVAILABLE_IOS(3_0);

响应链

响应链是“事件派发”的原则和规定,那么响应链是什么?顾名思义事件链是一个链条,详细的定义如下: 每条链是一个 链表状结构,整个是一棵树,链表的每一个node是一个 UIResponser对象。

事件响应链的形成和事件的响应和传递,UIResponder都帮我们做了很多事。我们的app中,所有的视图都是按照一定的结构组织起来的,即树状层次结构,每个view都有自己的superView,包括controller的topmost view(controller的self.view)。当一个view被add到superView上的时候,他的nextResponder属性就会被指向它的superView,当controller被初始化的时候,self.view(topmost view)的nextResponder会被指向所在的controller,而controller的nextResponder会被指向self.view的superView,这样,整个app就通过nextResponder串成了一条链,也就是我们所说的响应链。所以响应链就是一条虚拟的链,并没有一个对象来专门存储这样的一条链,而是通过UIResponder的属性串连起来的。如下图:

An example of a responder chain

当一个事件发生时,如果 first responder 不处理,事件就会继续往下传递,被下个 responder 接收,如果下个 responder 也不处理,又会被下下个 responder 接收…… 直到一个 responder 处理了事件或者没有 responder 了。这些 responder 按照传递次序连接起来的链条就构成了响应者链。

由于不同的 app 内的布局和层次结构的不同,响应顺序也会有所不同,但事件的传递路径会遵守基本规则。从图中可以看到,响应者链有以下特点:

响应者链通常是由 initial view 开始;

UIView 的 nextResponder 它的 superview;如果 UIView 已经是其所在的UIViewController 的 top view,那么 UIView 的 nextResponder 就是 UIViewController;

UIViewController 如果有 Super ViewController,那么它的 nextResponder 为其 Super ViewController 最表层的 View;如果没有,那么它的 nextResponder 就是 UIWindow;

UIWindow 的 contentView 指向 UIApplication,将其作为 nextResponder;

UIApplication 是一个响应者链的终点,它的 nextResponder 指向nil,整个 responder chain 结束。

需要说明是,如果当前的 responder 不处理事件,并希望将其传递给 nextResponder 时,需要手动编写代码,才会继续往下传递,否则事件会被废弃。

总结

所以关于事件的链有两条:事件的响应链;Hit-Testing 时事件的传递链。

响应链:由离用户最近的view向系统传递。

initial view –> super view –> …..–> view controller –> window –> Application –> AppDelegate

Hit-Testing 链:由系统向离用户最近的view传递。

UIKit –> active app's event queue –> window –> root view –>……–>lowest view


借鉴以下文章

史上最详细的iOS之事件的传递和响应机制-原理篇  iOS触摸事件处理详解  事件处理  深入浅出iOS事件机制  iOS 点击事件传递及响应 iOS Events and Responder Chain

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容

  • 好奇触摸事件是如何从屏幕转移到APP内的?困惑于Cell怎么突然不能点击了?纠结于如何实现这个奇葩响应需求?亦或是...
    Lotheve阅读 56,596评论 51 597
  • 在iOS开发中经常会涉及到触摸事件。本想自己总结一下,但是遇到了这篇文章,感觉总结的已经很到位,特此转载。作者:L...
    WQ_UESTC阅读 5,987评论 4 26
  • iOS中的事件 响应者对象 - 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收...
    Hevin_Chen阅读 627评论 0 0
  • 原文来自:http://www.cnblogs.com/Quains/p/3369132.html 有时间我再来整...
    小如99阅读 202评论 0 0
  • iOS触摸事件处理 主要是记录下iOS的界面触摸事件处理机制,然后用一个实例来说明下应用场景.一、处理机制界面响应...
    醉叶惜秋阅读 548评论 0 0