天天看點

事件處理和響應者鍊條詳解

1、事件處理

      在使用者使用app過程中,會産生各種各樣的事件,iOS中的事件可以分為3大類型:觸摸事件、加速計事件和遠端控制事件,如下圖所示:

事件處理和響應者鍊條詳解

       這裡我們主要說說觸摸事件,發生觸摸事件後,系統會将該事件加入到一個由UIApplication管理的事件隊列,UIApplication會從事件隊列中取出最前面的事件,并将事件分發下去以便處理,通常,先發送事件給應用程式的主視窗(keyWindow)主視窗會在視圖層次結構中找到一個最合适的視圖來處理觸摸事件,這也是整個事件處理過程的第一步,找到合适的視圖控件後,就會調用視圖控件的touches方法來作具體的事件處理

 touchesBegan…  touchesMoved…  touchedEnded…       要想找到最合适的視圖來處理事件,首先我們得必須清楚事件是如何傳遞的,如下圖所示:

事件處理和響應者鍊條詳解

         觸摸事件的傳遞是從父控件傳遞到子控件,我們來分析下以下幾種視圖被點選後事件的傳遞過程 點選了綠色的view:

UIApplication->UIWindow->白色 ->綠色

點選了藍色的view:

UIApplication->UIWindow->白色 ->橙色 ->藍色

點選了黃色的view:

UIApplication->UIWindow->白色 ->橙色 ->藍色 ->黃色

        值得注意的是: 如果父控件不能接收觸摸事件,那麼子控件就不可能接收到觸摸 事件。         那麼問題來了,如何找到最合适的控件來處理事件?可以通過2點因素判斷: 1、自己是否能接收觸摸事件; 2、觸摸點是否在自己身上。        之後就從後往前周遊子控件( 注:先周遊後添加的子控件),重複前面的兩個步驟,如果沒有符合條件的子控件,那麼就自己最适合處理,這就是觸摸事件的傳遞。        那麼UIView在什麼情況下不能接收觸摸事件呢?一共有三種情況: 1.不接收使用者互動

userInteractionEnabled = NO

2.隐藏

hidden = YES

3.透明

alpha = 0.0 ~ 0.01

提示:UIImageView的userInteractionEnabled預設就是NO,是以UIImageView以及它的子控件預設是不能接收觸摸事件的。

                                                                 觸摸事件處理的詳細過程

       使用者點選螢幕後産生的一個觸摸事件,經過一些列的傳遞過程後,會找到最合适的視圖控件來處理這個事件。找到最合适的視圖控件後,就會調用控件的touches方法來作具體的事件處理 touchesBegan… touchesMoved… touchedEnded…        如果最合适的視圖控件沒有實作touchs方法,這些touches方法的預設做法是将事件順着 響應者鍊條向上傳遞,将事件交給 上一個響應者進行處理。         2、響應者鍊條       下圖是我從Apple官方文檔截下來的關于響應者鍊條的示意圖:

事件處理和響應者鍊條詳解
事件處理和響應者鍊條詳解

         參照以上兩幅圖,我們基本可以理清 響應 者鍊的事件傳遞過 程: 1.如果目前處理事件的view是控制器的view,就傳遞給控制器(上一個響應者);其他情況下,則将其傳遞給它的父視圖(上一個響應者) 2.在視圖層次結構的最頂級視圖,如果也不能處理收到的事件或消息,則其将事件或消息傳遞給window對象進行處理 3.如果window對象也不處理,則其将事件或消息傳遞給UIApplication對象 4.如果UIApplication也不能處理該事件或消息,則将其丢棄        其實這裡和事件處理裡說的上一個響應者也就是官方文檔截圖裡标注的nextResponder,如果目前處理觸摸事件的view沒有實作touchs方法,則會找尋它的nextResponder,如果沒有則繼續找,繼而形成一個響應者鍊條,而且我們可以發現它的傳遞過程和事件處理的傳遞過程正好相反,形成一個回路似的路線