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

以上是本人寫代碼時推斷的,當然手勢識別有各種類型,不可能僅僅這幾行代碼就能實現.

如有錯誤之處,請指出,共同進步


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM