iPhone開發(fā)指南之事件處理介紹
iPhone開發(fā)指南之事件處理介紹是本文要介紹的內(nèi)容,主要來講解一下關(guān)于iphone中的事件處理的內(nèi)容,先來看詳細(xì)內(nèi)容。
事件處理
本章描述了iPhone操作系統(tǒng)里的事件類型,并解釋了如何處理它們。還討論了怎么在一個應(yīng)用程序里以及應(yīng)用程序之間利用UIPasteboard類提供的機(jī)制來拷貝和粘貼數(shù)據(jù),這是在iPhone OS 3.0中引入的。
事件和事件類型
一個event 是一個代表用戶事件的對象-也就是,iPhone OS探測到的用戶動作,比如手指觸摸或者設(shè)備抖動。在Cocoa Touch中,事件是UIEvent 類的實(shí)例。當(dāng)一個用戶事件發(fā)生時-比如,手指觸摸屏幕或滑過表面-系統(tǒng)將不斷發(fā)送事件對象給應(yīng)用程序來處理。
iPhone OS 目前支持兩種類型的事件:觸摸事件和運(yùn)動事件。UIEvent 類在iPhone OS 3.0中得到擴(kuò)展,不僅可以支持這兩種事件類型而且還可以容納將來更多的事件種類。列表3-1中列舉了已聲明的枚舉常量。
事件類型和事件子類型常量
- typedef enum {
- UIEventTypeTouches,
- UIEventTypeMotion,
- } UIEventType;
- typedef enum {
- UIEventSubtypeNone = 0,
- UIEventSubtypeMotionShake = 1,
- } UIEventSubtype;
每個事件具備如上其中之一的事件類型和與之相關(guān)聯(lián)的子類型,你可以通過UIEvent的type和subtype 屬性來訪問。事件類型包含觸摸和運(yùn)動事件。在iPhone OS 3.0里,只有一個振動-運(yùn)動子類型(UIEventSubtypeMotionShake);而觸摸事件總包含一個UIEventSubtypeNone子類型。
你不該在代碼中retain一個UIEvent對象。如果你需要維持一個事件對象的當(dāng)前狀態(tài)以備后面使用,你應(yīng)該用一個合適的方式來拷貝并保存這些狀態(tài)位(比如,使用一個實(shí)例變量或一個字典對象)。
遞交事件
事件的遞交遵循一個特定的路徑。如“Core Application Architecture,” 所描述。當(dāng)用戶觸摸設(shè)備屏幕時,iPhone OS識別這個觸摸事件序列并打包進(jìn)一個UIEvent對象放置在當(dāng)前激活應(yīng)用程序的事件隊(duì)列中。如果這個系統(tǒng)解釋設(shè)備的振動為一個運(yùn)動事件,那么代表相應(yīng)事件的對象也會放到應(yīng)用程序的事件隊(duì)列中。
管理應(yīng)用程序的單件UIApplication 對象從隊(duì)列頂端獲取一個事件并派發(fā)。通常,它發(fā)送這個事件給這個應(yīng)用程序的關(guān)鍵窗口-擁有接受用戶事件焦點(diǎn)的窗口-然后代表這個窗口的UIWindow 對象發(fā)送事件給一個初始對象來進(jìn)行處理。這個對象對觸摸事件和運(yùn)動事件是不同的。
觸摸事件。 窗口對象使用點(diǎn)擊檢測(hit-testing)以及響應(yīng)鏈(responder chain) 來查找接收該觸摸事件的視圖。在點(diǎn)擊檢測中,一個窗口在視圖層次的最上面的視圖中調(diào)用hitTest:withEvent:; 如果這個方法返回YES,則在該視圖層次的每個視圖上遞歸調(diào)用pointInside:withEvent:,這樣進(jìn)行下去直到發(fā)現(xiàn)這個在觸摸事件發(fā)生范圍內(nèi)的子視圖。這個視圖就成為hit-test 視圖。
如果這個hit-test 視圖不能處理這個事件,這個事件將按照響應(yīng)鏈進(jìn)行回溯,如“Responder Objects and the Responder Chain” 所描述,直到系統(tǒng)找到一個視圖可以處理它。一個觸摸對象(在“Touch Events”中描述)在其生命周期中和它的hit-test視圖相關(guān)聯(lián),即便這個對象代表的觸摸接下來移到視圖之外。“Hit-Testing” 討論了點(diǎn)擊檢測的編程含義。
運(yùn)動事件。 這個窗口對象發(fā)送運(yùn)動事件給第一響應(yīng)者來處理。(第一響應(yīng)者在“Responder Objects and the Responder Chain.”中描述)。
盡管hit-test視圖和第一響應(yīng)者通常是相同的視圖對象,但并非必須如此。
UIApplication 對象和每個UIWindow 對象在“Touch Events”方法中分發(fā)事件。 (這些類用同樣的簽名聲明了一個方法)。因?yàn)檫@些方法是事件進(jìn)入一個應(yīng)用程序的漏斗點(diǎn),你可以子類化UIApplication 或UIWindow 并重寫(override)sendEvent: 方法來監(jiān)控事件(很少有程序需要這樣做)。如果你重寫這些方法,請確認(rèn)調(diào)用超類的實(shí)現(xiàn)(也就是,[super sendEvent:theEvent]);永遠(yuǎn)不要去玩弄事件分發(fā)。
響應(yīng)對象和響應(yīng)鏈
前面的討論提到了響應(yīng)者的概念。那么什么是一個響應(yīng)者對象以及它在事件遞交的架構(gòu)中如何工作的呢?
一個響應(yīng)者對象(responder object)是一個能響應(yīng)事件并處理它們的對象。UIResponder 是所有響應(yīng)者對象的基類。它不僅僅為事件處理也為公共的響應(yīng)者行為定義了編程接口。UIApplication, UIView, 和所有的自UIView以下直接或間接繼承于UIResponder的UIKit類 (包括UIWindow),那么它們的實(shí)例就是響應(yīng)者對象。
第一響應(yīng)者(first responder) 是處于一個應(yīng)用程序中的響應(yīng)者對象(通常是一個UIView對象),該對象被指定為非觸摸事件的第一個接收者。一個UIWindow 在消息中給第一響應(yīng)者發(fā)送這些事件,給它處理過程中的第一鏡頭。要接收這些消息,響應(yīng)者對象必須實(shí)現(xiàn)canBecomeFirstResponder并返回YES;它還必須接收一個becomeFirstResponder消息(可以自我觸發(fā))。第一響應(yīng)者是一個窗口的第一個視圖來接收下面這些類型的事件和消息:
運(yùn)動事件-通過調(diào)用 UIResponder 運(yùn)動處理方法,在“Motion Events”中有詳細(xì)描述
動作消息-當(dāng)用戶操作一個控件(比如一個按鈕或滑動條)時發(fā)送并且沒有為這個動作消息指定目標(biāo)
菜單編輯消息-當(dāng)用戶點(diǎn)擊編輯菜單的命令時發(fā)送 (在 “Copy, Cut, and Paste Operations” 有詳細(xì)描述)
第一響應(yīng)者在文本編輯中也起作用。一個處于編輯焦點(diǎn)中的文本視圖或者文本框被作為第一響應(yīng)者,這將導(dǎo)致虛擬鍵盤被呈現(xiàn)出來。
注意: 應(yīng)用程序必須顯式的設(shè)置一個第一響應(yīng)者來處理運(yùn)動事件,動作消息和菜單編輯消息;UIKit會自動把用戶點(diǎn)擊的文本框和文本視圖設(shè)置為第一響應(yīng)者。
如果第一響應(yīng)者或者點(diǎn)擊檢測(hit-test)視圖沒有處理一個事件,它可能會傳遞事件(通過消息)給響應(yīng)鏈中的下一個響應(yīng)者,看看它是否能處理。
響應(yīng)鏈?zhǔn)且粋€響應(yīng)者對象的連接序列,事件或動作消息(或菜單編輯消息)依次傳遞。它允許響應(yīng)者對象把事件處理的職責(zé)轉(zhuǎn)交給其它更高層的對象。應(yīng)用程序通過向上傳遞一個事件來查找合適的處理對象。因?yàn)辄c(diǎn)擊檢測視圖也是一個響應(yīng)者對象,應(yīng)用程序在處理觸摸事件時也可以利用響應(yīng)鏈。響應(yīng)鏈由一系列的下一個響應(yīng)者組成,如圖3-1所示:
Figure 3-1 iPhone OS中的響應(yīng)鏈
當(dāng)系統(tǒng)遞交一個事件時,它首先發(fā)給一個特定視圖。對于觸摸事件,這個特定視圖就是hitTest:withEvent:返回的那個;對于運(yùn)動事件和動作消息,這個視圖就是第一響應(yīng)者。如果這個初始視圖不處理這個事件,它將按一個特定路徑回溯響應(yīng)鏈:
1、點(diǎn)擊檢測視圖或者第一響應(yīng)者傳遞事件或動作消息給它的視圖控制器如果它有的話;如果沒有一個視圖控制器,就傳遞給它的父視圖(superview)。
2、如果一個視圖或者它的視圖控制器不能處理這個事件或動作消息,它將傳遞給該視圖的父視圖。
3、在這個視圖層次中的每個后續(xù)的父視圖遵循上述的模式,如果它不能處理這個事件或動作消息的話。
4、最頂層的視圖如果不能處理這個事件或動作消息,就傳遞給UIWindow對象來處理。
5、如果UIWindow 對象不能處理,就傳給單件應(yīng)用程序?qū)ο骍IApplication。
如果應(yīng)用程序?qū)ο笠膊荒芴幚磉@個事件或動作消息,將拋棄它。
如果你實(shí)現(xiàn)了一個自定義視圖來處理事件或動作消息,你不應(yīng)該直接轉(zhuǎn)發(fā)這個事件或消息給nextResponder 來回溯響應(yīng)鏈。相反應(yīng)該調(diào)用當(dāng)前事件處理方法的超類實(shí)現(xiàn)-而讓Uikit來處理響應(yīng)鏈的遍歷。
調(diào)整事件遞交
UIKit 為應(yīng)用程序提供了編程手段來簡化事件處理或者完全關(guān)閉事件流。下面的列表總結(jié)了這些方法:
(1)閉觸摸事件的遞交
缺省情況下,視圖接收觸摸事件,但是你可以設(shè)置它的userInteractionEnabled 屬性為NO來關(guān)閉事件提交。視圖在隱藏或透明時也不會接收事件。
(2)在一段時間內(nèi)關(guān)閉觸摸事件的遞交
應(yīng)用程序可以調(diào)用UIApplication 方法beginIgnoringInteractionEvents并稍后調(diào)用endIgnoringInteractionEvents 方法。第一個方法使應(yīng)用程序完全停止接收觸摸事件消息;第二個方法恢復(fù)接收消息。有些時候你想關(guān)掉事件接收比如正在執(zhí)行動畫。
(3)開啟多點(diǎn)觸摸的遞交
缺省情況下,視圖忽略多點(diǎn)觸摸事件序列中除了第一次觸摸以外的其它所有事件。如果你想這個視圖處理多點(diǎn)觸摸,你必須為這個視圖開啟這個能力。通過編程設(shè)置你的視圖的multipleTouchEnabled 屬性為YES, 或者在Interface Builder這個視圖的inspector里設(shè)置相關(guān)屬性。
(4)限制事件遞交給單個視圖
缺省情況下,一個視圖的exclusiveTouch 屬性被設(shè)置為NO, 這意味著這個視圖不會阻塞該窗口中的其它視圖接收觸摸事件。如果你把這個屬性設(shè)置為YES,你標(biāo)記這個視圖以便,當(dāng)它跟蹤觸摸時,它是當(dāng)前窗口中唯一可以跟蹤觸摸的視圖。窗口中的其它視圖將不能接收觸摸事件。不過,被標(biāo)記為“exclusive touch”的視圖不能接收相同窗口中其它視圖相關(guān)的觸摸事件。如果一個手指接觸了一個exclusive-touch 視圖, 那么這個觸摸事件僅在該視圖是當(dāng)前窗口中唯一跟蹤這個手指的視圖時才會被遞交出去。如果一個手指觸摸了一個non-exclusive 視圖, 那么這個觸摸事件僅在沒有其它手指被一個exclusive-touch 視圖跟蹤時才會被遞交出去。
(5)限制事件遞交給子視圖
一個自定義UIView 類可以重寫hitTest:withEvent: 來限制多點(diǎn)觸摸事件遞交給它的子視圖。請查看關(guān)于這個技術(shù)的討論“Hit-Testing”。
小結(jié):iPhone開發(fā)指南之事件處理介紹的內(nèi)容介紹完了,希望本文對你有所幫助!