iOS开发事件分发机制—响应链—手势影响
1、提纲
- 什么是iOS的事件分发机制 ?
- 一个事件UIEvent又是如何响应的?
- 手势对于响应链有何影响?
2、事件分发机制
2.1、来源
以直接触摸事件为例:
- 当用户一个手指触摸屏幕是会生成一个UITouch对象,多个手指就是多个对象,手指移动系统会更新对象的相应信息。
- 系统会将UITouch对象封装生成一个事件UIEvent对象,将这个事件交给最佳具有响应能力的视图处理。
- 系统有个UIResponder类,只有继承UIResponder的类才具有响应事件能力,所以UIKit系统控件大多是继承此类。
如何找到处理这个事件的视图的过程——事件分发机制
2.2、具体步骤
2.2.1、事件Event的产生
点击一下iOS设备的屏幕,UIKit就会生成一个事件对象UIEvent,然后会把这个Event分发给当前活动的app;
当前活动的app得知有事件,UIApplication 单例就会从事件队列中去取最新的事件,然后分发给能够处理该事件的对象(具体视图)。
2.2.2、运用到的两个UIView中的方法
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event; //找到并返回最合适的视图来
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event; //判断点是否在视图内
当一个视图View收到hitTest消息时,会调用自己的poinInside方法;
如果返回YES,View会遍历自己的子视图(遍历顺序先addSubView先遍历),子视图就会调用自己的hitTest方法;
如果返回NO,View就不会遍历自己子视图(很节约);
直到找到最小的能够处理事件的view,如果整了一圈没找到能够处理的view,则返回自身。
2.2.3、举例说明
白色:ViewController , 绿色:一个View视图 , 蓝色:一个Button按钮
现象:点击绿色视图内的按钮区域,正常;点击绿色视图外的按钮区域,按钮的selector方法不会调用?

重新绿色view的hitTest方法:

点击有效区域时:返回视图坐标{{88, -26}, {47, 52}},此坐标是相对父视图的;
点击区域外的部分时:返回视图坐标{{0, 0}, {0, 0}},所以按钮不会响应;
重新hitTest方法,修改返回view,当点击区域外按钮部分时也返回有效视图{{88, -26}, {47, 52}},如图所示;
另外一种解决方案:更暴力
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
return YES;
}
号外:
如果触摸点不在 view 中,直接返回 nil (例子就是此现象)。
3、响应链
. UIView 的 nextResponder 是直接管理它的 UIViewController (也就是 VC.view.nextResponder = VC ),如果当前 View 不是 ViewController 直接管理的 View,则 nextResponder 是它的 superView( view.nextResponder = view.superView )。
. UIViewController 的 nextResponder 是它直接管理的 View 的 superView( VC.nextResponder = VC.view.superView )。
如果viewcontroller的view是window的根view,那么下一个响应者是window;
如果viewcontroller是另一个viewcontroller模态推出的,那么下一个响应者是另一个viewcontroller;
如果viewcontroller的view被add到另一个viewcontroller的根view上,那么下一个响应者是另一个viewcontroller的根view
. UIWindow 的 nextResponder 是 UIApplication 。
. UIApplication 的 nextResponder 是 AppDelegate。
一般来说,某个 UIResponder 的子类想要自己处理一些事件,就需要重写它的这些方法(触摸为例):
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);
如果想自己处理后,继续让事件响应下去:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
} - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
} - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
} - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
}
4、手势对响应链有何影响
手势识别器并不是响应者链中的一员,但是手势识别器会观察touch事件,并延迟事件向所绑定的视图传递;
在上例中给Button和view添加点击手势:

按钮会优先响应手势,而不是自身的selector;
设置手势代理:让按钮响应自身的selector
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if ([touch.view isKindOfClass:[UIButton class]]) {
return NO;
}else{
return YES;
}
}

添加手势又屏蔽:有毛病?
在其他UICollectionView和UIScrollView、UITableView等,如果需要在视图上添加手势,cell上也会响应手势,此方法可以解决手势和自身方法的冲突!
iOS开发事件分发机制—响应链—手势影响的更多相关文章
- iOS学习9_事件分发&响应链
iOS的三种事件:触摸事件/运动事件/远程控制事件 typedef enum { UIEventTypeTouches, UIEventTypeMotion, UIEventTypeRemoteCon ...
- IOS 触摸事件分发机制详解
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:MelonTeam 前言 很多时候大家都不关心IOS触摸事件的分发机制的实现原理,当遇到以下几种情形的时候你很可能抓破头皮都找不到解决方案 ...
- Android开发——事件分发机制详解
0. 前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52566965 深入学习事件分发机制,是为了解决在Android开发中 ...
- cocos2d-x游戏引擎核心(3.x)----事件分发机制之事件从(android,ios,desktop)系统传到cocos2dx的过程浅析
(一) Android平台下: cocos2dx 版本3.2,先导入一个android工程,然后看下AndroidManifest.xml <application android:label= ...
- 【Unity游戏开发】用C#和Lua实现Unity中的事件分发机制EventDispatcher
一.简介 最近马三换了一家大公司工作,公司制度规范了一些,因此平时的业余时间多了不少.但是人却懒了下来,最近这一个月都没怎么研究新技术,博客写得也是拖拖拉拉,周六周天就躺尸在家看帖子.看小说,要么就是 ...
- View的事件分发机制解析
引言 Android事件构成 在Android中,事件主要包含点按.长按.拖拽.滑动等,点按又包含单击和双击,另外还包含单指操作和多指操作.全部这些都构成了Android中的事件响应.总的来说.全部的 ...
- Android事件分发机制二:viewGroup与view对事件的处理
前言 很高兴遇见你~ 在上一篇文章 Android事件分发机制一:事件是如何到达activity的? 中,我们讨论了触摸信息从屏幕产生到发送给具体 的view处理的整体流程,这里先来简单回顾一下: 触 ...
- Android面试必问!View 事件分发机制,看这一篇就够了!
在 Android 开发当中,View 的事件分发机制是一块很重要的知识.不仅在开发当中经常需要用到,面试的时候也经常被问到. 如果你在面试的时候,能把这块讲清楚,对于校招生或者实习生来说,算是一块不 ...
- Android事件分发机制浅谈(二)--源码分析(ViewGroup篇)
上节我们大致了解了事件分发机制的内容,大概流程,这一节来分析下事件分发的源代码. 我们先来分析ViewGroup中dispatchTouchEvent()中的源码 public boolean dis ...
随机推荐
- vue基础五
条件渲染 1.v-if 1.1<template>中v-if条件组 因为 v-if 是一个指令,需要将它添加到一个元素上.但是如果我们想切换多个元素呢?此时我们可以把一个<templ ...
- luoguP1290 欧几里德的游戏 [博弈论]
题目描述 欧几里德的两个后代Stan和Ollie正在玩一种数字游戏,这个游戏是他们的祖先欧几里德发明的.给定两个正整数M和N,从Stan开始,从其中较大的一个数,减去较小的数的正整数倍,当然,得到的数 ...
- Delphi实现提取可执行文件内部所有图标
本实例实现的功能是能够从用户选择的可执行文件(后缀名为exe)中提取所有图标并且显示在窗体上. 在窗体中添加TImage 组件.TOpenDialog组件和TButton组件,TImage组件充当显示 ...
- psql内部命令及对应sql语句
\?: 查看所有帮助 \l: 查看所有数据库 SELECT d.datname as "Name", pg_catalog.pg_get_userbyid(d.da ...
- nteract 使用教程
安装 直接去官网下载 一路回车 官网 建立python虚拟环境 和我们平时一样 不同的是在建立完之后 要安装一个kernel Using Python3 with pip and a virtual ...
- git分布式版本控制系统权威指南学习笔记(五):git checkout
文章目录 分离头指针 通过cat可以查看当前的分支 通过branch查看当前分支 checkout commitId(真正的
- 1022 Digital Library (30 分)
1022 Digital Library (30 分) A Digital Library contains millions of books, stored according to thei ...
- Codeforces 1191B Tokitsukaze and Mahjong
题目链接:http://codeforces.com/problemset/problem/1191/B 题意:类似于麻将,三个一样花色一样数字的,或者三个同花顺就赢了,新抽的能当任何类型,问至少几个 ...
- Java内存通道
对文件执行I/O的另一种方法是将文件的一个区域映射到物理内存,并将其作为内存数组.可以使用MappedByteBuffer来执行内存映射文件I/O. 要使用内存映射文件I/O,请为文件获取FileCh ...
- ios网络学习------2 用非代理方法实现同步post请求
#pragma mark - 这是私有方法,尽量不要再方法中直接使用属性,由于一般来说属性都是和界面关联的,我们能够通过參数的方式来使用属性 #pragma mark post登录方法 -(void) ...