久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Responder Chain(ios事件傳遞)

 嘆落花 2015-03-13

一.responder對象

在iOS系統(tǒng)中,,能夠響應(yīng)并處理事件的對象稱之為responder object, UIResponder是所有responder對象的基類,,在UIResponder類中定義了處理各種事件,包括觸摸事件(Touch Event),、運動事件(Motion Event)和遠程控制事件(Remote-Control Events)的編程接口,,其中處理觸摸事件(Touch Event)的編程接口如下:
– touchesBegan:withEvent:
– touchesMoved:withEvent:
– touchesEnded:withEvent:
– touchesCancelled:withEvent:
這四個方法分別處理觸摸開始事件,觸摸移動事件,,觸摸終止事件,,以及觸摸跟蹤取消事件。

UIApplicationUIViewController,UIView和所有繼承自UIView的UIKit類(包括UIWindow,繼承自UIView)都直接或間接的繼承自UIResponder,所以它們的實例都是responder object對象,都實現(xiàn)了上述4個方法,。UIResponder中的默認實現(xiàn)是什么都不做,,但UIKit中UIResponder的直接子類(UIView,UIViewController…)的默認實現(xiàn)是將事件沿著responder chain繼續(xù)向上傳遞到下一個responder,即nextResponder。所以在定制UIView子類的上述事件處理方法時,,如果需要將事件傳遞給next responder,可以直接調(diào)用super的對應(yīng)事件處理方法,,super的對應(yīng)方法將事件傳遞給next responder,即使用

[super touchesBegan:touches withEvent:event];

不建議直接向nextResponder發(fā)送消息,這樣可能會漏掉父類對這一事件的其他處理,。

[self.nextResponder  touchesBegan:touches withEvent:event];

另外,在定制UIView子類的事件處理方法時,,如果其中一個方法沒有調(diào)用super的對應(yīng)方法,則其他方法也需要重寫,不使用super的方法,,否則事件處理流程會很混亂,。

注:UIKit框架的類層次結(jié)構(gòu)圖見:UIKit Framework Reference

二.responder chain

上文提到了responder chain,responder chain是一系列連接的responder對象,通過responder對象可以將處理事件的責(zé)任傳遞給下一個,,更高級的對象,即當(dāng)前responder對象的nextResponder,。
iOS中responder chain的結(jié)構(gòu)為:

  • UIView的nextResponder屬性,如果有管理此view的UIViewController對象,則為此UIViewController對象,;否則nextResponder即為其superview,。
  • UIViewController的nextResponder屬性為其管理view的superview.
  • UIWindow的nextResponder屬性為UIApplication對象。
  • UIApplication的nextResponder屬性為nil,。

iOS系統(tǒng)在處理事件時,,通過UIApplication對象和每個UIWindow對象的sendEvent:方法將事件分發(fā)給具體處理此事件的responder對象(對于觸摸事件為hit-test view,其他事件為first responder),當(dāng)具體處理此事件的responder不處理此事件時,可以通過responder chain交給上一級處理。

  1. 如果hit-test view或first responder不處理此事件,,則將事件傳遞給其nextResponder處理,,若有UIViewController對象則傳遞給UIViewController,傳遞給其superView,。
  2. 如果view的viewController也不處理事件,,則viewController將事件傳遞給其管理view的superView。
  3. 視圖層級結(jié)構(gòu)的頂級為UIWindow對象,,如果window仍不處理此事件,,傳遞給UIApplication.
  4. 若UIApplication對象不處理此事件,則事件被丟棄,。

三.巧妙利用nextResponder

通過UIViewController的view屬性可以訪問到其管理的view對象,及此view的所有subviews,。但是根據(jù)一個view對象,沒有直接的方法可以得到管理它的viewController,但我們使用responder chain可以間接的得到,代碼如下:

@implementation UIView (ParentController)
-(UIViewController*)parentController{
    UIResponder *responder = [self nextResponder];
    while (responder) {
	if ([responder isKindOfClass:[UIViewController class]]) {
		return (UIViewController*)responder;
	}
	responder = [responder nextResponder];
    }
    return nil;
}
@end



iOS事件機制(一)

DEC 7TH, 2013

運用的前提是掌握 掌握的本質(zhì)是理解

本篇內(nèi)容將圍繞iOS中事件及其傳遞機制進行學(xué)習(xí)和分析,。在iOS中,,事件分為三類:

  • 觸控事件(單點、多點觸控以及各種手勢操作)
  • 傳感器事件(重力,、加速度傳感器等)
  • 遠程控制事件(遠程遙控iOS設(shè)備多媒體播放等)

這三類事件共同構(gòu)成了iOS設(shè)備豐富的操作方式和使用體驗,,本次就首先來針對第一類事件:觸控事件,進行學(xué)習(xí)和分析,。

Gesture Recognizers

Gesture Recognizers是一類手勢識別器對象,,它可以附屬在你指定的View上,并且為其設(shè)定指定的手勢操作,,例如是點擊,、滑動或者是拖拽。當(dāng)觸控事件 發(fā)生時,,設(shè)置了Gesture Recognizers的View會先通過識別器去攔截觸控事件,,如果該觸控事件是事先為View設(shè)定的觸控監(jiān)聽事件,那么Gesture Recognizers將會發(fā)送動作消息給目標(biāo)處理對象,,目標(biāo)處理對象則對這次觸控事件進行處理,,先看看如下流程圖。

在iOS中,,View就是我們在屏幕上看到的各種UI控件,,當(dāng)一個觸控事件發(fā)生時,Gesture Recognizers會先獲取到指定的事件,然后發(fā)送動作消息(action message)給目標(biāo)對象(target),,目標(biāo)對象就是ViewController,,在ViewController中通過事件方法完成對該事件的處理。Gesture Recognizers能設(shè)置諸如單擊,、滑動,、拖拽等事件,通過Action-Target這種設(shè)計模式,,好處是能動態(tài)為View添加各種事件監(jiān)聽,,而不用去實現(xiàn)一個View的子類去完成這些功能。

以上過程就是我們在開發(fā)中在方法中常見的設(shè)置action和設(shè)置target,,例如為UIButton設(shè)置監(jiān)聽事件等,。

常用手勢識別類

在UIKit框架中,系統(tǒng)為我們事先定義好了一些常用的手勢識別器,,包括點擊,、雙指縮放、拖拽,、滑動、旋轉(zhuǎn)以及長按,。通過這些手勢識別器我們可以構(gòu)造豐富的操作方式,。

在上表中可以看到,UIKit框架中已經(jīng)提供了諸如UITapGestureRecognizer在內(nèi)的六種手勢識別器,,如果你需要實現(xiàn)自定義的手勢識別器,,也可以通過繼承UIGestureRecognizer類并重寫其中的方法來完成,這里我們就不詳細討論了,。

每一個Gesture Recognizer關(guān)聯(lián)一個View,,但是一個View可以關(guān)聯(lián)多個Gesture Recognizer,因為一個View可能還能響應(yīng)多種觸控操作方式,。當(dāng)一個觸控事件發(fā)生時,,Gesture Recognizer接收一個動作消息要先于View本身,結(jié)果就是Gesture Recognizer作為View處理觸控事件的代表,,或者叫代理,。當(dāng)Gesture Recognizer接收到指定的事件時,它就會發(fā)送一條動作消息(action message)給ViewController并處理,。

連續(xù)和不連續(xù)動作

觸控動作同時分為連續(xù)動作(continuous)和不連續(xù)動作(discrete),,連續(xù)動作例如滑動和拖拽,它會持續(xù)一小段時間,,而不連續(xù)動作例如單擊,,它瞬間就會完成,在這兩類事件的處理上又稍有不同。對于不連續(xù)動作,,Gesture Recognizer只會給ViewContoller發(fā)送一個單一的動作消息(action message),而對于連續(xù)動作,,Gesture Recognizer會發(fā)送多條動作消息給ViewController,直到所有的事件都結(jié)束,。

為一個View添加GestureRecognizer有兩種方式,,一種是通過InterfaceBuilder實現(xiàn),另一種就是通過代碼實現(xiàn),,我們看看通過代碼來如何實現(xiàn),。

MyViewContoller.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)viewDidLoad {
     [super viewDidLoad];

     // 創(chuàng)建并初始化手勢對象
     UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
          initWithTarget:self action:@selector(respondToTapGesture:)];

     // 指定操作為單擊一次
     tapRecognizer.numberOfTapsRequired = 1;

     // 為當(dāng)前View添加GestureRecognizer
     [self.view addGestureRecognizer:tapRecognizer];

     // ...
}

通過上述代碼,我們實現(xiàn)了為當(dāng)前MyViewController的View添加一個單擊事件,,首先構(gòu)造了UITapGestureRecognizer對象,,指定了target為當(dāng)前ViewController本身,action就是后面自己實現(xiàn)的處理方法,,這里就呼應(yīng)了前文提到的Action-Target模式,。

在事件處理過程中,這兩種方式所處的狀態(tài)又各有不同,,首先,,所有的觸控事件最開始都是處于可用狀態(tài)(Possible),對應(yīng)UIKit里面的UIGestureRecognizerStatePossible類,,如果是不連續(xù)動作事件,,則狀態(tài)只會從Possible轉(zhuǎn)變?yōu)橐炎R別狀態(tài)(Recognized,UIGestureRecognizerStateRecognized)或者是失敗狀態(tài)(Failed,UIGestureRecognizerStateFailed)。例如一次成功的單擊動作,,就對應(yīng)了Possible-Recognized這個過程,。

如果是連續(xù)動作事件,如果事件沒有失敗并且連續(xù)動作的第一個動作被成功識別(Recognized),,則從Possible狀態(tài)轉(zhuǎn)移到Began(UIGestureRecognizerStateBegan)狀態(tài),,這里表示連續(xù)動作的開始,接著會轉(zhuǎn)變?yōu)镃hanged(UIGestureRecognizerStateChanged)狀態(tài),,在這個狀態(tài)下會不斷循環(huán)的處理連續(xù)動作,,直到動作執(zhí)行完成變轉(zhuǎn)變?yōu)镽ecognized已識別狀態(tài),最終該動作會處于完成狀態(tài)(UIGestureRecognizerStateEnded),,另外,,連續(xù)動作事件的處理狀態(tài)會從Changed狀態(tài)轉(zhuǎn)變?yōu)镃anceled(UIGestureRecognizerStateCancelled)狀態(tài),原因是識別器認為當(dāng)前的動作已經(jīng)不匹配當(dāng)初對事件的設(shè)定了,。每個動作狀態(tài)的變化,,Gesture Recognizer都會發(fā)送消息(action message)給Target,也就是ViewController,,它可以根據(jù)這些動作消息進行相應(yīng)的處理,。例如一次成功的滑動手勢動作就包括按下,、移動、抬起的過程,,分別對應(yīng)了Possible-Began-Changed-Recognized這個過程,。

UITouch & UIEvent

在屏幕上的每一次動作事件都是一次Touch,在iOS中用UITouch對象表示每一次的觸控,,多個Touch組成一次Event,,用UIEvent來表示一次事件對象。

在上述過程中,,完成了一次雙指縮放的事件動作,,每一次手指狀態(tài)的變化都對應(yīng)事件動作處理過程中得一個階段。通過Began-Moved-Ended這幾個階段的動作(Touch)共同構(gòu)成了一次事件(Event),。在事件響應(yīng)對象UIResponder中有對應(yīng)的方法來分別處理這幾個階段的事件,。

  • touchesBegan:withEvent:
  • touchesMoved:withEvent:
  • touchesEnded:withEvent:
  • touchesCancelled:withEvent:

后面的參數(shù)分別對應(yīng)UITouchPhaseBegan、UITouchPhaseMoved,、UITouchPhaseEnded,、UITouchPhaseCancelled這幾個類。用來表示不同階段的狀態(tài),。

事件傳遞

如上圖,,iOS中事件傳遞首先從App(UIApplication)開始,接著傳遞到Window(UIWindow),,在接著往下傳遞到View之前,,Window會將事件交給GestureRecognizer,如果在此期間,,GestureRecognizer識別了傳遞過來的事件,則該事件將不會繼續(xù)傳遞到View去,,而是像我們之前說的那樣交給Target(ViewController)進行處理,。

響應(yīng)者鏈(Responder Chain)

通常,一個iOS應(yīng)用中,,在一塊屏幕上通常有很多的UI控件,,也就是有很多的View,那么當(dāng)一個事件發(fā)生時,,如何來確定是哪個View響應(yīng)了這個事件呢,,接下來我們就一起來看看。

響應(yīng)者對象(Responsder Object)

響應(yīng)者對象是能夠響應(yīng)并且處理事件的對象,,UIResponder是所有響應(yīng)者對象的父類,,包括UIApplication、UIView和UIViewController都是UIResponder的子類,。也就意味著所有的View和ViewController都是響應(yīng)者對象,。

第一響應(yīng)者(First Responder)

第一響應(yīng)者是第一個接收事件的View對象,,我們在Xcode的Interface Builder畫視圖時,可以看到視圖結(jié)構(gòu)中就有First Responder,。

這里的First Responder就是UIApplication了,。另外,我們可以控制一個View讓其成為First Responder,,通過實現(xiàn) canBecomeFirstResponder方法并返回YES可以使當(dāng)前View成為第一響應(yīng)者,,或者調(diào)用View的becomeFirstResponder方法也可以,例如當(dāng)UITextField調(diào)用該方法時會彈出鍵盤進行輸入,,此時輸入框控件就是第一響應(yīng)者,。

事件傳遞機制

如上所說,,,如果hit-test view不能處理當(dāng)前事件,,那么事件將會沿著響應(yīng)者鏈(Responder Chain)進行傳遞,知道遇到能處理該事件的響應(yīng)者(Responsder Object),。通過下圖,,我們來看看兩種不同情況下得事件傳遞機制。

左邊的情況,,接收事件的initial view如果不能處理該事件并且她不是頂層的View,,則事件會往它的父View進行傳遞。initial view的父View獲取事件后如果仍不能處理,,則繼續(xù)往上傳遞,,循環(huán)這個過程。如果頂層的View還是不能處理這個事件的話,,則會將事件傳遞給它們的ViewController,,如果ViewController也不能處理,則傳遞給Window(UIWindow),,此時Window不能處理的話就將事件傳遞給Application(UIApplication),,最后如果連Application也不能處理,則廢棄該事件,。

右邊圖的流程唯一不同就在于,,如果當(dāng)前的ViewController是由層級關(guān)系的,那么當(dāng)子ViewController不能處理事件時,,它會將事件繼續(xù)往上傳遞,,直到傳遞到其Root ViewController,后面的流程就跟之前分析的一樣了,。

這就是事件響應(yīng)者鏈的傳遞機制,,通過這些內(nèi)容,我們可以更深入的了解事件在iOS中得傳遞機制,,對我們在實際開發(fā)中更好的理解事件操作的原理有很大的幫助,,也對我們實現(xiàn)復(fù)雜布局進行事件處理時增添了多一份的理解,。


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多