刚学完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详解的更多相关文章

  1. iOS中—触摸事件详解及使用

    iOS中--触摸事件详解及使用 (一)初识 要想学好触摸事件,这第一部分的基础理论是必须要学会的,希望大家可以耐心看完. 1.基本概念: 触摸事件 是iOS事件中的一种事件类型,在iOS中按照事件划分 ...

  2. 1.0 iOS中的事件

    本文并非最终版本,如有更新或更正会第一时间置顶,联系方式详见文末 如果觉得本文内容过长,请前往本人 “简书”   在用户使用app过程中,会产生各种各样的事件,iOS中的事件可以分为3大类型: UIK ...

  3. 响应者链条,iOS中touchs事件的处理流程。

    用户在使用app的时候,会产生各样的事件.在iOS中的事件可以分为三种 触摸事件(Touch Event) 加速计事件(Accelerometer Event) 远程控制事件(Remote Contr ...

  4. iOS中的事件响应链、单例模式、工厂模式、观察者模式

    学习内容 欢迎关注我的iOS学习总结--每天学一点iOS:https://github.com/practiceqian/one-day-one-iOS-summary iOS中事件传递和相应机制 i ...

  5. 李洪强iOS经典面试题155 - const,static,extern详解(面试必备)

    李洪强iOS经典面试题155 - const,static,extern详解(面试必备) 一.const与宏的区别(面试题): const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽 ...

  6. appledoc导出iOS代码文档的使用和问题详解(干货篇)

    appledoc导出iOS代码文档的使用和问题详解(干货篇) 1. 简单说一下背景和自己感受 背景: 项目好像突然黄了,公司让详细写项目代码的注释并且导出文档,弄完之后就要封版. 说实话:听到这个消息 ...

  7. amazeui中的js插件有哪些(详解功能)

    amazeui中的js插件有哪些(详解功能) 一.总结 一句话总结: 二.amazeui中的js插件有哪些 1.UI 增强 警告框Alert 按钮交互Button 折叠面板Collapse 下拉组件D ...

  8. vue2.x版本中computed和watch的使用入门详解-computed篇

    前言 在基于vue框架的前端项目开发过程中,只要涉及到稍微复杂一点的业务,我们都会用到computed计算属性这个钩子函数,可以用于一些状态的结合处理和缓存的操作. 基础使用 在computed中,声 ...

  9. CSS中伪类及伪元素用法详解

    CSS中伪类及伪元素用法详解   伪类的分类及作用: 注:该表引自W3School教程 伪元素的分类及作用: 接下来让博主通过一些生动的实例(之前的作业或小作品)来说明几种常用伪类的用法和效果,其他的 ...

随机推荐

  1. 给jdk写注释系列之jdk1.6容器(2)-LinkedList源码解析

    LinkedList是基于链表结构的一种List,在分析LinkedList源码前有必要对链表结构进行说明.   1.链表的概念      链表是由一系列非连续的节点组成的存储结构,简单分下类的话,链 ...

  2. 【简单dp+模拟】hdu-5375(2015多校#7-1007)

    给你一个二进制数,,每一位有一个权值,让你转格雷码,求所对应格雷码位为1的权值的和:二进制位中的某些位为?,你需要给这些问号赋值使得到的和最大. 首先你得知道二进制转格雷码的规则,即格雷码位为[二进制 ...

  3. Android开发需要注意的坑

    Android开发需要注意的坑一览​对于一些Android开发过程中坑爹.细小,但又重要的错误的总结​Android开发在路上:少去踩坑,多走捷径其他参考: ​google官方版本发布图 ​umeng ...

  4. 纯css 写三角形

    <div style="width: 0;height: 0;border-left: 6px solid transparent;border-right: 6px solid tr ...

  5. Git CMD - reset: Reset current HEAD to the specified state

    命令格式 git reset [-q] [<tree-ish>] [--] <paths>…​ git reset (--patch | -p) [<tree-ish&g ...

  6. MYfirst

    终于有了自己的博客了,啊哈哈!

  7. Java之绘制五环图案

    前面已经介绍过绘制方法.这里不再赘述. package com.caiduping; import java.awt.BasicStroke; import java.awt.Color; impor ...

  8. Javascript中的函数

    Javascript中的函数 1.什么是函数 函数是被命名的,独立的,完成特定功能的代码段.其可能给调用它的程序返回值,我们把这个代码段就称之为"函数". 被命名的:函数大部分都是 ...

  9. 关于C/C++中的位运算技巧

    本篇文章讲述在学习CSAPP位运算LAB时的一些心得. 移位运算的小技巧 C/C++对于移位运算具有不同的策略,对于无符号数,左右移位为逻辑移位,也就是直接移位:对于有符号数,采用算术移位的方式,即左 ...

  10. HOWTO re

    \w 字母数字字符 [a-z A-Z 0-9_] \W 非字母数组字符 [^a-z-A-Z 0-9_] \d 十进制数字 [0-9] \D 非数字字符 [^0-9] \s 空白字符 [\t\n\r\f ...