iOS中touches事件,addtarget ...action和GestureRecognizer详解
刚学完uiview,uicontrol类,许多人知道 touchesBegain,touchesMoved,touchesEnd,GestureRecognizer的用途,但仔细考虑这些事件之间的关系,却令人头疼.
现在以一个例子来分析它们的内部实现:
- (void)viewDidLoad
{
UIButton * btn=[[UIButton alloc]initWithFrame:CGRectMake(20, 40, 50, 50)];
[self.view addSubview:btn];
btn.backgroundColor=[UIColor redColor];
[btn release];
UITapGestureRecognizer * tap11=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapmethod11:)];
[btn addGestureRecognizer:tap11];
[btn addTarget:self action:@selector(bthmethod:) forControlEvents:UIControlEventTouchUpInside];
//注意标红得这三句,下面会对其重点分析
}
-(void)tapmethod11:(UITapGestureRecognizer *)tap
{
NSLog(@"%@",tap);
}
-(void)bthmethod:(UIButton *)btn
{
NSLog(@"%@",btn);
}
在一个视图控制器viewDidLoad里面实例化一个button按钮, 添加两个事件 一个UIControlEventTouchUpInside,另一个手势事件UITapGestureRecognizer,
启动后单击会发现,程序只会执行手势事件
这是怎么回事?
首先先来分析UIButton这个类,这个类间接继承于UIView,那么UIButton里面就一定有
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
....
这几个事件
接下来看 [btn addTarget:self action:@selector(bthmethod:) forControlEvents:UIControlEventTouchUpInside]; 这句代码,
这句代码是当btn触发这个 UIControlEventTouchUpInside(鼠标单击事件)时,会触发当前控制器里面的bthmethod:这个方法.
那么在UIButton这个类中也就肯定有 [self performSelector:bthmethod: withObject:self ]这句代码
问题的关键就在这里,UIControlEventTouchUpInside 这个事件是在哪里触发的哪? 可以做一个实验(大家可以在自己电脑上试试),当单击这个按钮时,NSLOG打印出来的信息是在鼠标单击键弹起后打印出来,所有可以推断出 [self performSelector:bthmethod: withObject:self ]这句代码是写在 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 这个事件中(这里之所以确定是在事件中,因为这个委托方法一定是事件触发的)
所以touchesEnded代码先这样写
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self performSelector:bthmethod: withObject:self ];
}
下面在分析手势识别GestureRecognizer
手势识别继承于NSObject,似乎和UIButton没半点关联,但仔细分析会发现:
UITapGestureRecognizer * tap11=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapmethod11:)];
手势识别的初始化(此处以UITapGestureRecognizer为例) 和 addtarget action这个方法类似
说明在手势识别这个类中,同样会有 [self performSelector:tapmethod11: withObject:self ];这句代码
但手势识别不是继承于UIView,所有它没有touch事件
我们先假设他的类中有一个method1方法,那么代码可以这样表达
@implement UITapGestureRecognizer
-(void)method
{
[self performSelector:tapmethod11: withObject:self ];
}
@end
大家应该知道,这个方法并非事件方法,那么平白无故是不可能被调用,但我们在单击按钮时却触发了,原因是什么?
接下来看 [btn addGestureRecognizer:tap11];这句,这时UIButton的一个方法
UIButton中调用这个方法,就可以实现手势识别
可以推断出UIButton中有一个 私有字段 UIGestureRecognizer * gesture;(为什么是私有,因为是共有我们就可以在它的定义中看到)
那么上面的[btn addGestureRecognizer:tap11];就是给 gesture赋值
赋值后gesture 调用 method方法就会指向上面的事件
具体代码如下:
@interface UIButton()
{
UIGestureRecognizer * gesture;
}
@end
@implementation UIButton
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[gesture method];
[self performSelector:bthmethod: withObject:self ];
}
@end
我们现在已经推理处touchesEnded里面有两句代码
但是单击按钮只执行了gesture 的方法,所有代码经过改进如下,得到如下结论
@implementation UIButton
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if(gesture!=nil)
{
[gesture method];
}
else
{
[self performSelector:bthmethod: withObject:self ];
}
}
@end
这就解释了开始我们提出的问题,为什么手势和单击事件只会响应手势
其实经过以上的推理,我们也就可以解释gesture为什么也会有手势开始( UIGestureRecognizerStateBegan),改变( UIGestureRecognizerStateChanged,),结束( UIGestureRecognizerStateEnded, )等状态
因为它完全就是UIView事件的生命周期的副本
那么UIButton类的最终版本是:
@interface UIButton()
{
UIGestureRecognizer * gesture;
}
@end
@implementation UIButton
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[gesture method];
[self performSelector:bthmethod: withObject:self ];
}
@end
我们现在已经推理处touchesEnded里面有两句代码
但是单击按钮只执行了gesture 的方法,所有代码经过改进如下,得到如下结论
@implementation UIButton
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if(gesture!=nil)
{
gesture.state=UIGestureRecognizerStateEnded;
[gesture method];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if(gesture!=nil)
{
gesture.state=UIGestureRecognizerStateChanged;
[gesture method];
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if(gesture!=nil)
{
gesture.state=UIGestureRecognizerStateBegan;
[gesture method];
}
else
{
[self performSelector:bthmethod: withObject:self ];
}
}
....
@end
以上是本人写代码时推断的,当然手势识别有各种类型,不可能仅仅这几行代码就能实现.
如有错误之处,请指出,共同进步
iOS中touches事件,addtarget ...action和GestureRecognizer详解的更多相关文章
- iOS中—触摸事件详解及使用
iOS中--触摸事件详解及使用 (一)初识 要想学好触摸事件,这第一部分的基础理论是必须要学会的,希望大家可以耐心看完. 1.基本概念: 触摸事件 是iOS事件中的一种事件类型,在iOS中按照事件划分 ...
- 1.0 iOS中的事件
本文并非最终版本,如有更新或更正会第一时间置顶,联系方式详见文末 如果觉得本文内容过长,请前往本人 “简书” 在用户使用app过程中,会产生各种各样的事件,iOS中的事件可以分为3大类型: UIK ...
- 响应者链条,iOS中touchs事件的处理流程。
用户在使用app的时候,会产生各样的事件.在iOS中的事件可以分为三种 触摸事件(Touch Event) 加速计事件(Accelerometer Event) 远程控制事件(Remote Contr ...
- iOS中的事件响应链、单例模式、工厂模式、观察者模式
学习内容 欢迎关注我的iOS学习总结--每天学一点iOS:https://github.com/practiceqian/one-day-one-iOS-summary iOS中事件传递和相应机制 i ...
- 李洪强iOS经典面试题155 - const,static,extern详解(面试必备)
李洪强iOS经典面试题155 - const,static,extern详解(面试必备) 一.const与宏的区别(面试题): const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽 ...
- appledoc导出iOS代码文档的使用和问题详解(干货篇)
appledoc导出iOS代码文档的使用和问题详解(干货篇) 1. 简单说一下背景和自己感受 背景: 项目好像突然黄了,公司让详细写项目代码的注释并且导出文档,弄完之后就要封版. 说实话:听到这个消息 ...
- amazeui中的js插件有哪些(详解功能)
amazeui中的js插件有哪些(详解功能) 一.总结 一句话总结: 二.amazeui中的js插件有哪些 1.UI 增强 警告框Alert 按钮交互Button 折叠面板Collapse 下拉组件D ...
- vue2.x版本中computed和watch的使用入门详解-computed篇
前言 在基于vue框架的前端项目开发过程中,只要涉及到稍微复杂一点的业务,我们都会用到computed计算属性这个钩子函数,可以用于一些状态的结合处理和缓存的操作. 基础使用 在computed中,声 ...
- CSS中伪类及伪元素用法详解
CSS中伪类及伪元素用法详解 伪类的分类及作用: 注:该表引自W3School教程 伪元素的分类及作用: 接下来让博主通过一些生动的实例(之前的作业或小作品)来说明几种常用伪类的用法和效果,其他的 ...
随机推荐
- 解决浏览器background-image属性不支持css3动画
问题 最近在使用background-image属性来实现css3的逐帧动画时,碰到了个问题.在chrome浏览器上,background-image属性是支持css3动画的,但是到了firefox上 ...
- Linux(CentOS)安装rar和unrar以及rar和unrar命令的使用
可以参考此篇博文. http://www.cnblogs.com/linjiqin/archive/2013/03/24/2979736.html 不过我按照其步骤手动安装Linux的rar文件执 ...
- Java从Jar文件中动态加载类
动态加载jar包,在实际开发中经常会需要用到,尤其涉及平台和业务的关系的时候,业务逻辑部分可以独立出去交给业务方管理,业务方只需要提供jar包,就能在平台上运行. 下面通过一个实例来直观演示: 第一: ...
- Servlet & JSP - Servlet API Overview
Servlet & Generic & HttpServlet 类图 Servlet 的生命周期 init.service 和 destroy 是 servlet 的生命周期方法,它们 ...
- Networking - ARP 协议
ARP 协议概述 ARP(Address Resolution Protocol),即地址解析协议,用于把 IP 地址映射到物理地址.网段上的每台主机都维护着一个被称为 ARP Table 或 ARP ...
- HDOJ2022海选女主角
海选女主角 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- Java集合类 java.util包
概述 软件包 类 使用 树 已过时 索引 帮助 JavaTM Platform Standard Ed. 6 上一个软件包 下一个软件包 框架 无框架 ...
- Ajax-Demo
index.jsp 1 <%@ page language="java" contentType="text/html; charset=UTF-8" p ...
- Could not load the "defaultimg" image referenced from a nib in the bundle with identifier "com.abc"
出现这个错误提示,是因为在xib中使用了.jpg格式的图片,在图片名称后面加上.jpg即可;
- 【转载】应广大群众的要求,今天开始连载《超容易的Linux系统管理入门书》一书
学习Linux容易嘛?我说超容易,你肯定不信.那学习Linux最好的学习方法是什么,就是脑子里面一直提问题,不停的提,时时刻刻提,如果你没有问题,那再容易的学习书你也看不懂. <超容易的Linu ...