譯自官方文檔:Using Responders and the Responder Chain to Handle Eventsapp
App 使用響應者對象接收和處理事件。一個響應者對象能夠是UIResponder
類的任何實例,常見的子類包括UIView
,UIViewController
和UIApplication
。響應者接收原始事件數據,而且必定會處理事件或將其發送給另外一個響應者對象。當 app 接收到事件時,UIKit
會自動將該事件定向到最合適的響應者對象,即第一響應者(the first responder)。框架
未處理的事件會在一個活動的響應者鏈中,從一個響應者傳遞到另外一個響應者,這是響應者對象的動態配置(?)。 下圖顯示了一個 app 中的響應者,該程序的界面包含一個UILabel
,一個UITextField
,一個UIButton
和兩個背景UIView
。 該圖還顯示了事件如何沿着響應者鏈從一個響應者轉移到下一個響應者。測試
若是UITextField
不處理事件,則UIKit
會將事件發送到UITextField
的父視圖,而後再接下來會發送到UIWindow
的根視圖。從根視圖開始,響應程序鏈在將事件定向到UIWindow
以前轉移到當前持有的UIViewController
。若是UIWindow
沒法處理事件,則UIKit
會將事件傳遞給UIApplication
對象,若是該對象是UIResponder
的實例而且還不是響應者鏈的一部分,則可能傳遞給app delegate(?)。ui
UIKit
是根據事件的類型將對象指定爲該事件的第一響應者。事件類型包括:code
事件類型 | 第一響應者 |
---|---|
Touch events | 發生觸摸的視圖 |
Press events | 被 focus 的對象 |
Shake-motion events | 你(或UIKit )指定的對象 |
Remote-control events | 你(或UIKit )指定的對象 |
Editing menu messages | 你(或UIKit )指定的對象 |
注意cdn
與加速度計,陀螺儀和磁力計有關的運動事件不遵循響應程序鏈。 相反,Core Motion 會將這些事件直接傳遞到指定的對象。 有關更多信息,請參見 Core Motion 框架。對象
控件使用action信息直接與其關聯的目標對象進行通訊。當用戶與控件交互時,控件會將action信息發送到其target對象。action消息不是事件,可是它們仍然能夠利用響應者鏈。當控件的目標對象爲nil
時,UIKit
從目標對象開始並遍歷響應程序鏈,直到找到實現適當操做方法的對象爲止。例如,UIKit
編輯菜單使用此行爲來搜索響應者對象,這些對象實現了諸如cut(_ :)
,copy(_ :)
或paste(_ :)
之類的方法。blog
手勢識別器(Gesture recognizers)會比相關視圖先接收觸摸和按下事件。若是視圖的手勢識別器沒法識別一系列觸摸,則UIKit
會將觸摸發送到視圖。 若是視圖沒法處理觸摸,UIKit
會將它們向上傳遞到響應者鏈。 有關使用手勢識別器處理事件的更多信息,請參見處理UIKit
手勢。事件
UIKit使用基於視圖的命中測試(hit-testing)來肯定觸摸事件發生的位置。具體來講,UIKit將觸摸位置與視圖層次結構中視圖對象的邊界(bounds of view objects)進行比較。UIView
的hitTest(_:with :)
方法會遍歷視圖層次結構,查找包含指定觸摸的最深子視圖,該子視圖成爲觸摸事件的第一響應者。ip
注意
若是觸摸位置在視圖範圍(a view’s bounds)以外,則
hitTest(_:with :)
方法將忽略該視圖及其全部子視圖。所以,若是視圖的clipsToBounds
屬性爲false
,即便該視圖剛好包含觸摸,也不會返回該視圖範圍以外的子視圖。有關命中測試(hit-testing)行爲的更多信息,請參見UIView
中有關hitTest(_:with :)
方法的討論。
發生觸摸時,UIKit
將建立一個UITouch
對象並將其與視圖關聯。 隨着觸摸位置或其餘參數的更改,UIKit
會使用新信息更新那個UITouch
對象。 惟一不變的屬性是那個關聯的視圖。 (即便觸摸位置移到原始視圖以外,觸摸的視圖屬性中的值也不會更改。)觸摸結束時,UIKit
會釋放UITouch
對象。
您能夠經過覆蓋響應者對象的next
(指響應鏈中下一個響應者)屬性來更改響應者鏈。
許多UIKit
類已經重寫此屬性並返回特定的對象,包括:
UIView
,若是視圖是UIViewController
的根視圖,則下一個響應者是UIViewController
。不然,下一個響應者是視圖的父視圖。
UIViewController
若是UIViewController
的視圖是UIWindow
的根視圖,則下一個響應者是UIWindow
對象。
若是UIViewController
是由另外一個UIViewController
呈現的,則下一個響應者是第二個視圖控制器。
UIWindow
,窗口的下一個響應者是UIApplication
對象。
UIApplication
,下一個響應者是app delegate
.但僅當該app delegate
是UIResponder
的實例且不是視圖、UIViewController
或app對象自己時,纔是下一個響應者。
這篇文檔講得很淺,同時也講的不怎麼容易懂,想要更深刻理解響應鏈及手勢相關內容仍是須要閱讀更多其餘優秀資料。