事件處理以及響應(yīng)者鏈條(三)

事件的產(chǎn)生和傳遞

先調(diào)用hittest找到最適合響應(yīng)的控件,然后再用touchbegan把事件往下傳

完整過程

1> 先將事件對象由上往下傳遞(由父控件傳遞給子控件)趟畏,找到最合適的控件來處理這個事件。

2> 調(diào)用最合適控件的touches….方法

3> 如果調(diào)用了[super touches….];就會將事件順著響應(yīng)者鏈條往上傳遞牡肉,傳遞給上一個響應(yīng)者

4> 接著就會調(diào)用上一個響應(yīng)者的touches….方法

事件的發(fā)生

蘋果注冊了一個 Source1 (基于 mach port 的) 用來接收系統(tǒng)事件彪笼,其回調(diào)函數(shù)為 __IOHIDEventSystemClientQueueCallback()钻注。

當(dāng)一個硬件事件(觸摸/鎖屏/搖晃等)發(fā)生后,首先由 IOKit.framework 生成一個 IOHIDEvent 事件并由 SpringBoard 接收配猫。這個過程的詳細(xì)情況可以參考這里队寇。SpringBoard 只接收按鍵(鎖屏/靜音等),觸摸章姓,加速,接近傳感器等幾種 Event识埋,隨后用 mach port 轉(zhuǎn)發(fā)給需要的App進程凡伊。隨后蘋果注冊的那個 Source1 就會觸發(fā)回調(diào),并調(diào)用 _UIApplicationHandleEventQueue() 進行應(yīng)用內(nèi)部的分發(fā)窒舟。

_UIApplicationHandleEventQueue() 會把 IOHIDEvent 處理并包裝成 UIEvent 進行處理或分發(fā)系忙,其中包括識別 UIGesture/處理屏幕旋轉(zhuǎn)/發(fā)送給 UIWindow 等。通常事件比如 UIButton 點擊惠豺、touchesBegin/Move/End/Cancel 事件都是在這個回調(diào)中完成的银还。

包裝成UIEvent后,系統(tǒng)會將該事件加入到一個由UIApplication管理的事件隊列中

UIApplication會從事件隊列中取出最前面的事件洁墙,并將事件分發(fā)下去以便處理蛹疯,通常,先發(fā)送事件給應(yīng)用程序的主窗口(keyWindow)

主窗口會在視圖層次結(jié)構(gòu)中找到一個最合適的視圖來處理觸摸事件热监,這也是整個事件處理過程的第一步

第一步的具體流程捺弦,控件不斷調(diào)用以下代碼:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
//判斷當(dāng)前狀態(tài)是否不能響應(yīng)事件
    if(self.hidden == YES || self.alpha <= 0.01 || self.userInteractionEnabled == NO){
        return nil;
    }else if ([self pointInside:point withEvent:event] == NO){//判斷是否包含這個點,沒有就返回
        return nil;
    }else{//繼續(xù)遍歷
        return [super hitTest:point withEvent:event];
    }
}

hitest方法


4> 03-hitText方法和pointInside方法(02-事件傳遞代碼)
    * (了解hitText)學(xué)習(xí)一個方法必須了解:什么時候調(diào)用和這個方法有什么用
    1. hitText什么時候調(diào)用:當(dāng)一個事件傳遞給一個控件的時候孝扛,控件就會調(diào)用這個方法
    2. hitText作用: 尋找到最合適的view列吼。
    * (回顧下事件傳遞),UIApplication -> UIWindow
    *  UIWindow去尋找最合適的view? [UIWindow hitTest:withEvent:]里面做了什么事情苦始?
    1> 判斷窗口能不能處理事件? 如果不能寞钥,意味著窗口不是最合適的view,而且也不會去尋找比自己更合適的view,直接返回nil,通知UIApplication陌选,沒有最合適的view理郑。
    2> 判斷點在不在窗口
    3> 遍歷自己的子控件蹄溉,尋找有沒有比自己更合適的view
    4> 如果子控件不接收事件,意味著子控件沒有找到最合適的view,然后返回nil,告訴窗口沒有找到更合適的view,窗口就知道沒有比自己更合適的view,就自己處理事件香浩。
    * 驗證下hitTest方法返回nil类缤,里面的子控件能處理事件嗎? 重寫根控制器view的hitTest:withEvent:方法邻吭,
    * 驗證這個方法是否真能找到最合適的view餐弱?
    * 如果點擊屏幕任何一個地方,都是白色的view囱晴,怎么做膏蚓。直接返回白色的view,就不會繼續(xù)去找白色view的子控件了。
    * pointInside作用:判斷一個點在不在一個控件上
    * point參數(shù):方法調(diào)用者坐標(biāo)系上的點畸写,PPT畫圖分析原理驮瞧。

示例

Snip20150711_1.png

觸摸事件的傳遞是從父控件傳遞到子控件

  • 點擊了綠色的view:
    UIApplication -> UIWindow -> 白色 -> 綠色
  • 點擊了藍(lán)色的view:
    UIApplication -> UIWindow -> 白色 -> 橙色 -> 藍(lán)色
  • 點擊了黃色的view:
    UIApplication -> UIWindow -> 白色 -> 橙色 -> 藍(lán)色 -> 黃色

如果父控件不能接收觸摸事件,那么子控件就不可能接收到觸摸事件(掌握)

具體流程如下:

  • 如何找到最合適的控件來處理事件枯芬?
  • 自己是否能接收觸摸事件论笔?
  • 觸摸點是否在自己身上?
  • 從后往前遍歷子控件千所,重復(fù)前面的兩個步驟
  • 如果沒有符合條件的子控件狂魔,那么就自己最適合處理

三種情況下,控件不接收觸摸事件

  1. 控件的userinterfaceEnable = NO淫痰;
  2. 透明度低于0.01
  3. 控件被隱藏了

而且最楷,某個控件隱藏,或者透明度低于0.01待错,它的子控件都會看不見籽孙,同樣無法接受觸摸事件, 同時火俄,UIImageView的userinterfaceEnable默認(rèn)為NO犯建。

觸摸事件處理的詳細(xì)過程,響應(yīng)者鏈條

用戶點擊屏幕后產(chǎn)生的一個觸摸事件,經(jīng)過一系列的傳遞過程后瓜客,會找到最合適的視圖控件來處理這個事件

找到最合適的視圖控件后胎挎,就會調(diào)用控件的touches方法來作具體的事件處理
touchesBegan…
touchesMoved…
touchedEnded…

這些touches方法的默認(rèn)做法是將事件順著響應(yīng)者鏈條向上傳遞,將事件交給上一個響應(yīng)者進行處理

響應(yīng)者鏈條示意圖

響應(yīng)者鏈條:是由多個響應(yīng)者對象連接起來的鏈條
作用:能很清楚的看見每個響應(yīng)者之間的聯(lián)系忆家,并且可以讓一個事件多個對象處理犹菇。
響應(yīng)者對象:能處理事件的對象


Snip20150711_3.png

在頂級視圖(key window的視圖)上調(diào)用pointInside:withEvent:方法判斷觸摸點是否在當(dāng)前視圖內(nèi);
如果返回NO芽卿,那么A返回nil揭芍;
如果返回YES,那么它會向當(dāng)前視圖的所有子視圖(key window的子視圖)發(fā)送hitTest:withEvent:消息卸例,遍歷所有子視圖的順序是從subviews數(shù)組的末尾向前遍歷(從界面最上方開始向下遍歷)称杨。
如果有subview的hitTest:withEvent:返回非空對象則A返回此對象肌毅,處理結(jié)束(注意這個過程,子視圖也是根據(jù)pointInside:withEvent:的返回值來確定是返回空還是當(dāng)前子視圖對象的姑原。并且這個過程中如果子視圖的hidden=YES悬而、userInteractionEnabled=NO或者alpha小于0.1都會并忽略);
如果所有subview遍歷結(jié)束仍然沒有返回非空對象锭汛,則A返回頂級視圖笨奠;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市唤殴,隨后出現(xiàn)的幾起案子般婆,更是在濱河造成了極大的恐慌,老刑警劉巖朵逝,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔚袍,死亡現(xiàn)場離奇詭異,居然都是意外死亡配名,警方通過查閱死者的電腦和手機啤咽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渠脉,“玉大人宇整,你說我怎么就攤上這事×幔” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵涩哟,是天一觀的道長索赏。 經(jīng)常有香客問我,道長贴彼,這世上最難降的妖魔是什么潜腻? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮器仗,結(jié)果婚禮上融涣,老公的妹妹穿的比我還像新娘。我一直安慰自己精钮,他們只是感情好威鹿,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著轨香,像睡著了一般忽你。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上臂容,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天科雳,我揣著相機與錄音根蟹,去河邊找鬼。 笑死糟秘,一個胖子當(dāng)著我的面吹牛简逮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播尿赚,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼散庶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吼畏?” 一聲冷哼從身側(cè)響起督赤,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泻蚊,沒想到半個月后躲舌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡性雄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年没卸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秒旋。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡约计,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出迁筛,到底是詐尸還是另有隱情煤蚌,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布细卧,位于F島的核電站尉桩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贪庙。R本人自食惡果不足惜蜘犁,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望止邮。 院中可真熱鬧这橙,春花似錦、人聲如沸导披。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撩匕。三九已至助隧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背并村。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工巍实, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哩牍。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓棚潦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親膝昆。 傳聞我的和親對象是個殘疾皇子丸边,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容