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