理解cocoa和cocoa touch的响应者链
该文章翻译自:Understanding cocoa and cocoa touch responder chain。
转载注明出处:http://www.cnblogs.com/zhanggui/p/7157954.html
不管是在cocoa中还是在cocoa touch中,所有的Applications都有一个与之关联的事件队列,这个队列里面是许多不同来源的事件。为了处理事件流,每个application都持有一个run loop,此run loop将会以先进先出(first in first out)的顺序接收和派发事件。
当一个程序启动的时,对UIApplicationMain的调用将会创建一个UIApplication的单例对象,这个单例对象将会处理和调度系统发送到应用程序事件队列的事件。
Application将会接收下面来源的事件:
- UIControl Actions:这些事使用action-target模式注册的动作,例如button添加的动作。
- User events:来自用户的事件,例如touches、shakes、motion等等。
- 系统事件:例如内存过低、旋转等。
在被派发到适合的接收者之前,这些事件都会被上面提到的application单例对象处理一下。
UIControl Actions
UIControl Actions就是我们通过addTarget:action:forControlEvents:
方法为control对象添加的action,UIControl对象将会保持并记录所有通过action/target添加的action。
当用户在控件上执行事件的时候,或者当一个控件调用sendActionsForControlEvents
方法的时候,和该控件相关的action事件将会被发送到注册的target。
举个例子:
UIButton *button = [UIButton new];
[button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventouchUpInside];
当用户点击这个button的时候,事件将会被调度到UIAppication(使用UIcontrol内部的sendActionsForControlEvents副本),然后application会从事件队列里面读取并且在UIApplication的sendAction:to:from:forEvent:
方法里面调度,该方法的基本实现就是将在注册的目标上调用动作,在这种情况下,目标将接收buttonTapped方法。
如果我们把target置为nil:
[button addTarget:nil action:@selector(buttonTapped) forControlEvents:UIControlEventTouchUpInside];
此时sendAction:to:from:forEvent
将会将buttonTapped选择器发送到当前第一响应者,如果当前的第一响应者没有实现这个方法,那么它将被转发到下一个响应者,系统将会一直尝试在响应者链中去找一个可用的响应者,直到没有更多的响应者可用。在这种情况下,该操作将会被删除。
根据上面所说的,我们可以利用UIapplication单例对象的sendAction:to:from:forEvent
方法给第一响应者发送一个动作,将target置为 nil。
例如我们可以发送resignFirstResponder
消息给第一响应者来隐藏键盘:
[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
User Events
用户事件,例如touch事件和设备运动事件,这些事件发送到application的事件队列里面,如果用户事件是touch事件之外的任何事情,application将会分发这个调用给第一响应者,如果第一响应者无法处理,系统会继续响应者链查找适当的响应者。
对于touch事件,流程是不一样的。当系统检测到一个屏幕上的touch,它就会把这个touch发送给application,application会在其 _ touchesEvent内部方法中接收这个touch事件。
然后application将会使用sendEvent将此事件转发到UIWindow,收到此事件后的Window会开始测试视图(hit-testing),以便找到接收此touch的视图。
UIView将会使用hitTest:withEvent
的方法来查找在这个touch事件之下的视图,hit-test会通过调用每个view的pointInside:withEvent:
来检查该touch是否在当前view里面。
hitTest和pointInside将被递归调用,直到它达到最顶层的叶视图。这个view将会被作为touch的第一响应者来处理这次touch。
UIWindow 会将触摸事件发送到此视图。
- (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;
当一个事件发送到一个view的时候,这个view有下面三种选择:
- 由于上述四种方法的UIResponder base实现将事件转发给下一个响应者,那么如果视图没有实现他们的方法,则该方法将被转发到下一个响应者。
- 视图可以实现上述的任何一种方法,做一些处理,然后调用super,以让下一个响应者做一些额外的过程。
- 视图可以实现上述任何方法,并选择不将事件转发给下一个响应者。
如果视图选择不处理这个touch事件,那么该事件将会发送到响应者链,然后按照下面的路径执行:
- 第一响应者是收到测试的视图(touch下的视图)
- 下一个响应者是它的父视图
- 该响应者链在视图层次结构上继续进行,直到达到与视图控制器相关的视图
- 这个视图控制器将会是下一个响应者
- 如果这个视图控制器是根视图控制器,那么window就是下一个响应者
- application是window的下一个响应者
- 在响应者链最后的响应者是App delegate
System Events
系统也会发送事件给application单例,application单例将会接收这些系统相关的事件,然后把他们派发到App delegate,app delegate将会依次接收和处理这些事件。
The first responder
任何的UIResponder对象都可以通过调用或者接收becomeFirstResponder
方法来确定是否成为第一响应者,第一响应者将被接收到有机会对用户事件采取行动。然而,touch事件不会被发送到第一响应者,这些事件被发送到通过进行递归命中测试发现的视图。
除了上面提到的,第一响应者也会接收到他们的target置为nil的UIControl动作。
理解cocoa和cocoa touch的响应者链的更多相关文章
- Cocoa Touch事件处理流程--响应者链
Cocoa Touch事件处理流程--响应者链 作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/9264335 转载请注明 ...
- 《从零开始学Swift》学习笔记(Day 68)——Cocoa Touch设计模式及应用之响应者链与触摸事件
原创文章,欢迎转载.转载请注明:关东升的博客 应用与用户进行交互,依赖于各种各样的事件.事件响应者对象是可以响应事件并对其进行处理的对象,响应者链是由一系列链接在一起的响应者组成的.响应者链在事件处理 ...
- Cocoa与Cocoa Touch的区别
Cocoa是在Mac OS X系统上原生的一个编译环境.他包含两个框架,其实就是一系列的类库,Foundation和AppKit. 在你的iPhone等掌上设备上,使用的则是他的一个子类 - Coco ...
- Responder一点也不神秘————iOS用户响应者链完全剖析
一.事件分类 对于IOS设备用户来说,他们操作设备的方式主要有三种:触摸屏幕.晃动设备.通过遥控设施控制设备.对应的事件类型有以下三种: 1.触屏事件(Touch Event) 2.运动事件(Moti ...
- iOS Responder Chain 响应者链
一.事件分类 对于IOS设备用户来说,他们操作设备的方式主要有三种:触摸屏幕.晃动设备.通过遥控设施控制设备.对应的事件类型有以下三种: 1.触屏事件(Touch Event) 2.运动事件(Moti ...
- [置顶] Responder一点也不神秘————iOS用户响应者链完全剖析
这篇文章想跟大家分享的主旨是iOS捕获用户事件的各种情况,以及内部封装的一些特殊事件. 我们先从UIButton谈起,UIButton大家使用的太多了,他特殊的地方就在于其内置的普通Default/高 ...
- [New learn]响应者链机制介绍
1.简介 测试代码库:https://github.com/xufeng79x/EventHandler 响应者链是系统寻找事件相应者的一个路径,他是同touch事件的Hit-testing过程具有 ...
- iOS用户响应者链的那些事儿
这篇文章想跟大家分享的主旨是iOS捕获用户事件的各种情况,以及内部封装的一些特殊事件. 我们先从UIButton谈起,UIButton大家使用的太多了,他特殊的地方就在于其内置的普通Default/高 ...
- iOS响应者链和事件传递机制
原文来自:http://www.cnblogs.com/zhw511006/p/3517248.html 响应者链(Responder Chain) 通常,一个iOS应用中,在一块屏幕上通常有很多的U ...
随机推荐
- Linux系列教程(二十三)——Linux的服务管理
前面我们讲解Linux软件包管理之源码包.脚本安装包时,我们介绍了rpm包和源码包由于安装位置的不同,会对服务的启动造成影响,具体是什么,本篇博客我们来详细介绍. 1.Linux服务管理总览 我们可以 ...
- .NET之RabbitMQ学习笔记(一)-应用场景
使用场景 1.异步处理 用户注册后,需要发注册邮件和注册短信,传统的做法有两种1.串行的方式;2.并行的方式 (1)串行处理方式:注册信息写数据库-发送注册邮件-发送注册短信,等上述三个操作都执行完成 ...
- Python 日志处理(一) 按Nginx log_format 分割日志记录
要求:不使用正则 根据nginx 默认的日志记录格式,分割日志记录. log_format main '$remote_addr - $remote_user [$time_local] " ...
- 老男孩最新Python全栈开发视频教程(92天全)重点内容梳理笔记 看完就是全栈开发工程师
为什么要写这个系列博客呢? 说来讽刺,91年生人的我,同龄人大多有一份事业,或者有一个家庭了.而我,念了次985大学,年少轻狂,在大学期间迷信创业,觉得大学里的许多课程如同吃翔一样学了几乎一辈子都用不 ...
- 实现基于tomcat集群会话保持
1.实验环境 我们需要准备两台虚拟机,把这两台虚拟机组成集群,实现会话保持. 2.配置server1 2.1 修改nginx配置文件 [root@server1 ~]# vim /etc/nginx/ ...
- Docker技术浅谈:私有化部署的优势以及在顶象内部的应用实践
顶象全景式业务安全风控体系基于新一代风控体系构建,并采用Docker技术进行私有云和公有云部署.本文主要和大家分享下Docker容器技术和顶象风控系统私有化部署的优势以及Docker容器技术在顶象内部 ...
- MVC过滤器简单理解
之前对于MVC过滤器的理解一直处于很模糊的状态,就在网上找了一些很简单的案例做了一下学习,就找了一个比较容易理解的demo分享给大家. 新建一个MVC4项目,可以在global.asax文件中看到如下 ...
- Python之登录接口
要求 1.输入用户名密码2.认证成功后显示欢迎信息3.输错三次后锁定 思路 没有数据库,这里使用本地文件,一共需要两个文件: 黑名单的文件:黑名单里检测,不让登录 用户信息文件:将 ...
- 11个优秀的Android开发开源项目
一. 一个类似微信的时光轴效果 时光轴效果 项目地址 https://github.com/ljtyzhr/TimeLine 二. 安卓选择器类库,包括日期.时间.单项.双项选择器.城市地址选择器 ...
- HDU 2795 Billboard 线段树,区间最大值,单点更新
Billboard Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...