當(dāng)我們?cè)谑謾C(jī)上點(diǎn)擊靶剑、滑動(dòng)屏幕等操作進(jìn)入到相應(yīng)的頁(yè)面,手機(jī)是如何區(qū)分相應(yīng)指令并響應(yīng)的呢池充?其中又是經(jīng)歷了怎樣的過(guò)程呢桩引?
1. 什么是事件鏈?
如下圖所示收夸,點(diǎn)擊屏幕時(shí)坑匠,首先UIApplication對(duì)象先收到該點(diǎn)擊事件,再依次傳遞給它上面的所有子view卧惜,直到傳遞到最上層厘灼,即UIApplication——>UIWindow——>RootViewController——>View——>Button,即傳遞鏈咽瓷。而反之Button——>View——>RootViewController——>UIWindow——>UIApplication則為響應(yīng)鏈设凹。簡(jiǎn)單總結(jié),事件鏈包含傳遞鏈和響應(yīng)鏈忱详,事件通過(guò)傳遞鏈傳遞下去围来,通過(guò)響應(yīng)鏈找到相應(yīng)的UIResponse。
2. 傳遞鏈:由系統(tǒng)向離用戶最近的view傳遞匈睁,如上圖所示监透。
在點(diǎn)擊屏幕時(shí)系統(tǒng)會(huì)將點(diǎn)擊事件加入到UIApplication管理的事件隊(duì)列中;
而UIApplication會(huì)從消息隊(duì)列中取出該事件傳遞給UIWindow對(duì)象航唆;
在UIWindow中調(diào)用方法hitTest:withEvent:返回最終相應(yīng)的view胀蛮;
在hitTest:withEvent:方法中調(diào)用pointInside:withEvent:來(lái)判斷當(dāng)前點(diǎn)擊的點(diǎn)是否在UIWindow內(nèi)部,如若返回yes糯钙,則倒序遍歷其子視圖找到最終響應(yīng)的子view粪狼;
如果最終返回一個(gè)view,那么即為最終響應(yīng)view并結(jié)束事件傳遞任岸,如果無(wú)值返回則將UIWindow作為響應(yīng)者再榄。
其中核心方法如下,
方法hitTest:withEvent:用來(lái)找到最終響應(yīng)事件的view享潜。
方法pointInside困鸥,用來(lái)判斷點(diǎn)擊的位置是否在視圖范圍內(nèi)。
以下情況為UIView不接受事件處理的case:
3. 響應(yīng)鏈:由離用戶最近的view向系統(tǒng)傳遞剑按。如下所示疾就,
若view的vc存在澜术,則將該事件傳遞給其vc響應(yīng);如若不存在猬腰,則傳遞給其父視圖鸟废;
若view的最頂層不能處理事件,則傳遞給UIWindow進(jìn)行處理姑荷;
若UIWindow不能處理盒延,則傳遞給UIApplication;
若UIApplication不能處理厢拭,則將該事件丟棄兰英。
4.示例代碼如下