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详解,布布扣,bubuko.com

时间: 2024-08-01 10:44:32

iOS中touches事件,addtarget ...action和GestureRecognizer详解的相关文章

iOS中的事件传递和响应者链条

iOS中的事件传递和响应者链条 本文转自:http://www.linuxidc.com/Linux/2015-08/121270.htm 首先我们来看看ios中事件的产生和传递过程 1.发生触摸事件后,系统会将事件加入到一个由UIApplication管理的队列事件中来 2.UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会发发送事件给应用程序的主窗口 3.主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件 4.找到合适的视图控件后,就会调用视图

1.0 iOS中的事件

在用户使用app过程中,会产生各种各样的事件,iOS中的事件可以分为3大类型: UIKit可识别三种类型的输入事件: 触摸事件 加速计事件 / 运动事件 远程控制事件 UIResponder - 响应者对象 概念: 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件. 成员: UIApplication.UIViewController.UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件 UIResponder的内部

iOS中的事件

iOS中的事件 在用户使用app过程中,会产生各种各样的事件 iOS中的事件可以分为3大类型 -- 触摸事件 ---- 加速计事件 ---- 远程控制事件- 响应者对象 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件.我们称之为"响应者对象" UIApplication.UIViewController.UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件 UIResponder UIResponder内

IOS应用的执行过程以及生命周期详解

iOS的应用程序的生命周期,还有程序是运行在前台还是后台,应用程序各个状态的变换,这些对于开发者来说都是很重要的. iOS系统的资源是有限的,应用程序在前台和在后台的状态是不一样的.在后台时,程序会受到系统的很多限制,这样可以提高电池的使用和用户体验. //开发app,我们要遵循apple公司的一些指导原则,原则如下: 1.应用程序的状态 状态如下: Not running  未运行  程序没启动 Inactive          未激活        程序在前台运行,不过没有接收到事件.在没

Android View 事件分发机制源码详解(View篇)

前言 在Android View 事件分发机制源码详解(ViewGroup篇)一文中,主要对ViewGroup#dispatchTouchEvent的源码做了相应的解析,其中说到在ViewGroup把事件传递给子View的时候,会调用子View的dispatchTouchEvent,这时分两种情况,如果子View也是一个ViewGroup那么再执行同样的流程继续把事件分发下去,即调用ViewGroup#dispatchTouchEvent:如果子View只是单纯的一个View,那么调用的是Vie

Android中内容观察者的使用---- ContentObserver类详解

  转载请注明出处:http://blog.csdn.net/qinjuning 前言: 工作中,需要开启一个线程大量的查询某个数据库值发送了变化,导致的开销很大,后来在老大的指点下,利用了 ContentObserver完美的解决了该问题,感到很兴奋,做完之后自己也对ContentObserver做下总结. ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于 数据库技术中的触发器(Trigger),当ContentObs

PHPCMS V9模板中的常用变量、碎片代码详解

前面是变量,后面是调用变量的解释 {pc:content action="position"posid="12" thumb="1" order="id desc"num="10"} 图片新闻 {pc:contentaction="lists" catid="$r[catid]" num="1"thumb="1" order=&

day01_linux中与Oracle有关的内核参数详解

linux中与Oracle有关的内核参数详解 在安装Oracle的时候需要调整linux的内核参数,但是各参数代表什么含义呢,下面做详细解析. Linux安装文档中给出的最小值: fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.shmall = 2097152 kernel.shmmax = 4294967295 kernel.shmmni = 4096 kernel.sem = 250 32000 100 128 net.ipv4.ip

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

原文:CSS中伪类及伪元素用法详解 伪类的分类及作用: 注:该表引自W3School教程 伪元素的分类及作用: 接下来让博主通过一些生动的实例(之前的作业或小作品)来说明几种常用伪类的用法和效果,其他的读者可以自己尝试: :active  大致效果为用鼠标点击时,元素增加特效,鼠标松开时,特效消失.多用在按钮的点击上. 写法: 这里id为box的是一div块,在css中首先设置了他的基本样式,下面为加入:active伪类后需要修改的样式. 未点击时: 点击之后: :active.:hover.: