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