国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

iOS事件機(jī)制(一)

2019-11-14 18:37:28
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

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

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

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

Gesture Recognizers

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

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

以上過(guò)程就是我們?cè)陂_(kāi)發(fā)中在方法中常見(jiàn)的設(shè)置action和設(shè)置target,例如為UIButton設(shè)置監(jiān)聽(tīng)事件等。

常用手勢(shì)識(shí)別類(lèi)

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

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

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

連續(xù)和不連續(xù)動(dòng)作

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

為一個(gè)View添加GestureRecognizer有兩種方式,一種是通過(guò)InterfaceBuilder實(shí)現(xiàn),另一種就是通過(guò)代碼實(shí)現(xiàn),我們看看通過(guò)代碼來(lái)如何實(shí)現(xiàn)。

MyViewContoller.m

123456789101112131415
- (void)viewDidLoad {     [super viewDidLoad];     // 創(chuàng)建并初始化手勢(shì)對(duì)象     UITapGestureRecognizer *taPRecognizer = [[UITapGestureRecognizer alloc]          initWithTarget:self action:@selector(respondToTapGesture:)];     // 指定操作為單擊一次     tapRecognizer.numberOfTapsRequired = 1;     // 為當(dāng)前View添加GestureRecognizer     [self.view addGestureRecognizer:tapRecognizer];     // ...}

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

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

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

UITouch & UIEvent

在屏幕上的每一次動(dòng)作事件都是一次Touch,在iOS中用UITouch對(duì)象表示每一次的觸控,多個(gè)Touch組成一次Event,用UIEvent來(lái)表示一次事件對(duì)象。

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

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

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

事件傳遞

如上圖,iOS中事件傳遞首先從App(UIapplication)開(kāi)始,接著傳遞到Window(UIWindow),在接著往下傳遞到View之前,Window會(huì)將事件交給GestureRecognizer,如果在此期間,GestureRecognizer識(shí)別了傳遞過(guò)來(lái)的事件,則該事件將不會(huì)繼續(xù)傳遞到View去,而是像我們之前說(shuō)的那樣交給Target(ViewController)進(jìn)行處理。

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

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

尋找hit-test view

什么是hit-test view呢?簡(jiǎn)單來(lái)說(shuō)就是你觸發(fā)事件所在的那個(gè)View,尋找hit-test view的過(guò)程就叫做Hit-Testing。那么,系統(tǒng)是如何來(lái)執(zhí)行Hit-Testing呢,首先假設(shè)現(xiàn)在有如下這么一個(gè)UI布局,一種有ABCDE五個(gè)View。

假設(shè)一個(gè)單擊事件發(fā)生在了View D里面,系統(tǒng)首先會(huì)從最頂層的View A開(kāi)始尋找,發(fā)現(xiàn)事件是在View A或者其子類(lèi)里面,那么接著從B和C找,發(fā)現(xiàn)事件是在C或者其子類(lèi)里面,那么接著到C里面找,這時(shí)發(fā)現(xiàn)事件是在D里面,并且D已經(jīng)沒(méi)有子類(lèi)了,那么hit-test view就是View D啦。

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

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

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

第一響應(yīng)者是第一個(gè)接收事件的View對(duì)象,我們?cè)赬code的Interface Builder畫(huà)視圖時(shí),可以看到視圖結(jié)構(gòu)中就有First Responder。

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

事件傳遞機(jī)制

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

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

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

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

總結(jié)

通過(guò)前面的內(nèi)容分析,我們已經(jīng)學(xué)習(xí)并了解了如下內(nèi)容:

  • Gesture Recognizers,是用來(lái)控制手勢(shì)識(shí)別的過(guò)程和方法,并且其通過(guò)Action-Target模式與ViewController的通信的方式。連續(xù)和不連續(xù)手勢(shì)動(dòng)作情況下GestureRecognizer的狀態(tài)轉(zhuǎn)變。
  • UITouch和UIEvent對(duì)象,他們都是UIKit中來(lái)進(jìn)行事件處理的對(duì)象,多個(gè)UITouch對(duì)象構(gòu)成一個(gè)UIEvent對(duì)象,重寫(xiě)相應(yīng)的方法可以控制和處理事件各個(gè)階段的操作。
  • 系尋找hit-test view的方式、事件傳遞機(jī)、制響應(yīng)者鏈

后記:本篇是iOS事件傳遞機(jī)制的上篇,下篇將繼續(xù)討論多點(diǎn)觸控事件和手勢(shì)操作的內(nèi)容!


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 西安市| 奉新县| 稻城县| 兴宁市| 泰宁县| 西吉县| 兰西县| 方山县| 景东| 嘉善县| 六安市| 尉犁县| 米易县| 临桂县| 高尔夫| 望江县| 绥化市| 若尔盖县| 禹城市| 凌云县| 合肥市| 宁城县| 阳城县| 东莞市| 黄山市| 徐闻县| 汶上县| 剑川县| 陕西省| 山东| 武邑县| 景洪市| 浦北县| 利川市| 西丰县| 萨嘎县| 大安市| 南通市| 肥西县| 怀化市| 宿迁市|