iOS 事件响应链

响应链是如何形成的?


当我们触碰到屏幕的时候,整个iOS系统发生了什么呢?

这里有个思路需要转变一下,本质上,我们开发的app,里面所有的视图都是虚拟的,只是一堆代码,看起来,你的app有许多View的堆叠,而且是有层次的,你看起来触碰到了最上面的一个View,事实上屏幕只有一块啊,你触碰到的是冷冰冰的屏幕,因此第一个感知触摸事件的是操作系统,是他最先检测到屏幕上的压力,而不是你看上去触摸到的那个视图哟。

注意,这并不意味着系统会立刻处理此事件

虽然看起来app里面的控件和View是有层次的,但事实上屏幕只有一块,而且没有层次

我们如何才能构架出有层次的View呢?

苹果的办法是:画布模式,大家都见过画画,你如果在同一个地方画2笔,第二笔会覆盖第一笔,同样的,在屏幕上的同一地方有两个View,第二View会覆盖第一个View,因此在视觉上有了层次

也因此,当你触摸到屏幕上某个点的时候,其实系统并不能立刻确定你触摸的哪块View,因为多块View会有叠加、覆盖

系统会如何做呢?正如上文提到的,第一个响应的是底层系统


如上图,当我们点击View E的位置时,系统先响应,然后它会调用方法:

hitTest:withEvent:

该方法接受位置参数CGPoint,并从底层开始按照subview的顺序,测试该CGPoint在哪个View上,如果在该View上,则继续测试是否在View的subview上,对照上图,顺序如下:

1.触摸的CGPoint在View A上吗?在的,继续测试A的子视图View B、View C

2.在View B上吗?不。在View B上吗?在,继续B的子视图View D、View E

3.在View D上吗?不,且D无subview,结束此分支

4.在View E上吗?在,E无subview,结束此分支

5.结果形成了一个链,View A -->View C -->View E

还记得吗,系统第一时间检测到了触摸,但是并不立刻处理,而是通过上述的测试,得到了一个响应链,该链的最后一个,就是逻辑上最上层的视图,也就是这次触摸的First Responder

需要注意的是,所有的响应链都是父子视图的关系哟,如果View A、View C、 VIew E只是视觉上遮盖了,但是却不是superview、subview的关系,则事件是不会在两者之间传递的

从底层往上的好处就是,一层层测试的过程中,响应链已经形成,当View E无法处理此事件怎么办?按照响应链往上回溯即可,一直回溯到application,也无人处理此事件,则将事件丢弃,如下图

如果First Responder不响应,则往上传给下一个View,直到传给UIApplication,依然无人响应则丢弃事件


如何处理事件?


我们获取了触摸事件,那么如何响应这个触摸呢?

其中一个是,手势识别(Gesture Recognizer):iOS提供了UITapGestureRecognizer来识别手势,它必须挂在某个View上,当某个View上发生了触摸事件,UITapGestureRecognizer就会识别该触摸,如果符合我们定义的手势,则触发一个事件


UITapGestureRecognizer *tapG =[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapClick:)];

tapG.delegate=self;

tapG.numberOfTapsRequired=2; //需要触碰2次

tapG.numberOfTouchesRequired=1;//需要一个手指

[blueView addGestureRecognizer:tapG];//把手势识别关联到blueView上

上面就是一个手势识别,当你在blueView上,单指触碰2次,就会触发tapClick:方法

以上是比较固定,好识别的手势,有些手势是没有规律可循的,比如切水果游戏中,是一指滑动切水果,角色扮演游戏中,滑动手指会使人物走动,画图板app,手指移动会留下笔画,如何定义这些手势?

事实上,我们需要在手指移动的同时就响应它,而不是等他结束了再响应,否则你的游戏就会有延时,你的画板就会等你手指离开屏幕才出现笔画,多么low的app

苹果提供了方法,让你可以实时的响应手势

- (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;

从命名就可以看出,以上方法是何作用,顺带提一句这也是我们推荐的代码风格,从命名即可猜出用途

以上方法是UIResponder的方法,只要是他的子类,都是可以响应触摸事件的,并且按响应链顺序调用,子视图不响应,就调父视图的

哪些是UIResponder的子类呢,大家可以打开Xcode,按下shift+commond+0,打开帮助文档,可以看到每个类的继承顺序,截取几个给大家看看


看到了吗,UIView、UIViewController都是UIResponder的方法,现在想想,为啥一个View覆盖了下面的UIScrollView,你在View上滑动手指,下面的scrollView就不会滑动吗?如果这个View是scrollView的子视图,你按住View滑动,整个scrollView都滑动了呢?

答案:覆盖的情况下,他们不是父子视图的关系,不在一条响应链上,事件并没有传给scrollView,当然不会出现滑动。如果是子视图,则在一个响应链上,View本身如果不加手势识别,并不会处理触摸事件,就会传给scrollView,而scrollView已经写好如何响应滑动,就出现滑动的效果

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

推荐阅读更多精彩内容