zoukankan      html  css  js  c++  java
  • 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

    以上是本人写代码时推断的,当然手势识别有各种类型,不可能仅仅这几行代码就能实现.

    如有错误之处,请指出,共同进步

  • 相关阅读:
    标准模板库中的链表(list)
    C++接口
    qsort
    C++异常
    标准模板库中的向量(vector)
    后缀表达式/逆波兰表达式
    静态数据成员
    c++存储区域
    #define 和 const
    Git 的下载与安装
  • 原文地址:https://www.cnblogs.com/lingzeng/p/3849399.html
Copyright © 2011-2022 走看看