iOS中touches事件,addtarget ...action和GestureRecognizer詳解

來源:互聯網
上載者:User

標籤:style   color   os   io   for   問題   

  剛學完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

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

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.