1. 程式人生 > >iOS中的事件的產生和傳遞

iOS中的事件的產生和傳遞

事件 container 步驟 -s 重難點 format 希望 接受 這也

每一次將代碼打散再串聯就是一次重構。

https://www.jianshu.com/p/2e074db792ba

iOS中的事件的產生和傳遞

3.1.事件的產生

  • 發生觸摸事件後,系統會將該事件加入到一個由UIApplication管理的事件隊列中,為什麽是隊列而不是棧?因為隊列的特點是FIFO,即先進先出,先產生的事件先處理才符合常理,所以把事件添加到隊列。
  • UIApplication會從事件隊列中取出最前面的事件,並將事件分發下去以便處理,通常,先發送事件給應用程序的主窗口(keyWindow)。
  • 主窗口會在視圖層次結構中找到一個最合適的視圖來處理觸摸事件,這也是整個事件處理過程的第一步。
    找到合適的視圖控件後,就會調用視圖控件的touches方法來作具體的事件處理。

3.2.事件的傳遞

  • 觸摸事件的傳遞是從父控件傳遞到子控件
  • 也就是UIApplication->window->尋找處理事件最合適的view

註 意: 如果父控件不能接受觸摸事件,那麽子控件就不可能接收到觸摸事件

應用如何找到最合適的控件來處理事件?
  • 1.首先判斷主窗口(keyWindow)自己是否能接受觸摸事件
  • 2.判斷觸摸點是否在自己身上
  • 3.子控件數組中從後往前遍歷子控件,重復前面的兩個步驟(所謂從後往前遍歷子控件,就是首先查找子控件數組中最後一個元素,然後執行1、2步驟)
  • 4.view,比如叫做fitView,那麽會把這個事件交給這個fitView,再遍歷這個fitView的子控件,直至沒有更合適的view為止。
  • 5.如果沒有符合條件的子控件,那麽就認為自己最合適處理這個事件,也就是自己是最合適的view。

UIView不能接收觸摸事件的三種情況:

  • 不允許交互:userInteractionEnabled = NO
  • 隱藏:如果把父控件隱藏,那麽子控件也會隱藏,隱藏的控件不能接受事件
  • 透明度:如果設置一個控件的透明度<0.01,會直接影響子控件的透明度。alpha:0.0~0.01為透明。

註 意:默認UIImageView不能接受觸摸事件,因為不允許交互,即userInteractionEnabled = NO。所以如果希望UIImageView可以交互,需要設置UIImageView的userInteractionEnabled = YES。

總結一下

1.點擊一個UIView或產生一個觸摸事件A,這個觸摸事件A會被添加到由UIApplication管理的事件隊列中(即,首先接收到事件的是UIApplication)。
2.UIApplication會從事件對列中取出最前面的事件(此處假設為觸摸事件A),把事件A傳遞給應用程序的主窗口(keyWindow)。
3.窗口會在視圖層次結構中找到一個最合適的視圖來處理觸摸事件。(至此,第一步已完成)

技術分享圖片 index.png

如果想讓某個view不能處理事件(或者說,事件傳遞到某個view那裏就斷了),那麽可以通過剛才提到的三種方式。比如,設置其userInteractionEnabled = NO;那麽傳遞下來的事件就會由該view的父控件處理。
例如,不想讓藍色的view接收事件,那麽可以設置藍色的view的userInteractionEnabled = NO;那麽點擊黃色的view或者藍色的view所產生的事件,最終會由橙色的view處理,橙色的view就會成為最合適的view。
所以,不管視圖能不能處理事件,只要點擊了視圖就都會產生事件,關鍵在於該事件最終是由誰來處理!也就是說,如果藍色視圖不能處理事件,點擊藍色視圖產生的觸摸事件不會由被點擊的視圖(藍色視圖)處理!
註意:如果設置父控件的透明度或者hidden,會直接影響到子控件的透明度和hidden。如果父控件的透明度為0或者hidden = YES,那麽子控件也是不可見的!

3.3.(重難點)如何尋找最合適的view

應用如何找到最合適的控件來處理事件?
1.首先判斷主窗口(keyWindow)自己是否能接受觸摸事件
2.觸摸點是否在自己身上
3.從後往前遍歷子控件,重復前面的兩個步驟(首先查找數組中最後一個元素)
4.如果沒有符合條件的子控件,那麽就認為自己最合適處理

詳述:1.主窗口接收到應用程序傳遞過來的事件後,首先判斷自己能否接手觸摸事件。如果能,那麽在判斷觸摸點在不在窗口自己身上
   2.如果觸摸點也在窗口身上,那麽窗口會從後往前遍歷自己的子控件(遍歷自己的子控件只是為了尋找出來最合適的view)
   3.遍歷到每一個子控件後,又會重復上面的兩個步驟(傳遞事件給子控件,1.判斷子控件能否接受事件,2.點在不在子控件上)
   4.如此循環遍歷子控件,直到找到最合適的view,如果沒有更合適的子控件,那麽自己就成為最合適的view。
找到最合適的view後,就會調用該view的touches方法處理具體的事件。所以,只有找到最合適的view,把事件傳遞給最合適的view後,才會調用touches方法進行接下來的事件處理。找不到最合適的view,就不會調用touches方法進行事件處理。
註意:之所以會采取從後往前遍歷子控件的方式尋找最合適的view只是為了做一些循環優化。因為相比較之下,後添加的view在上面,降低循環次數。



作者:VV木公子
鏈接:https://www.jianshu.com/p/2e074db792ba
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處。

iOS中的事件的產生和傳遞