iOS的touchEvent的消費過程
在iOS系統(tǒng)中,一共有三種類型的Event, 分別是touch events, motion events和remote-control events。touch events是用戶觸摸屏幕時觸發(fā)的事件,motion events是用戶移動設備時觸發(fā)的事件,remote-control events是用戶通過配件觸發(fā)的事件(如耳機等線控或鎖頻時線控等)。我們用的最多,交互最多的當然就是touch events了。
閱讀開發(fā)文檔Event Handling Guide for iOS這一章,知道產(chǎn)生touches時,系統(tǒng)會將一系列的touches打包到UIEvent里,該UIEvent存儲在當前應用event queue里,然后dispatch queue里面的事件給當前的key window, window通過hitTest: withEvent方法找到能夠接受該event的view。在最頂層次的View里調(diào)用hitTest: withEvent,然后該方法再調(diào)用自身的pointInside: withEvent方法來判斷需不需要處理,如果pointInside: withEvent返回YES,則hitTest: withEvent遍歷所有subview,返回能夠消費這個event的view,否則的話自身處理。如果pointInside: withEvent返回NO,則沿著responder chain向super view或者view controller傳遞event。如果view能夠消費touch event,則系統(tǒng)會向該responder 發(fā)送touchesBegan: touchesMoved: touchesCancelled: touchesEnded:等消息,然后來處理產(chǎn)生的touch events。touch的生命周期是跟它的hitTestView綁定的,就是從hitTestView接受該touch開始直到該touch消失都跟該hitTestView綁定。
所以我們需要自行處理touch event時,需要實現(xiàn)touchesBegan: touchesMoved: touchesCancelled: touchesEnded:等方法,如果不需要自行處理,或者是同時保留系統(tǒng)處理,則我們只需調(diào)用如上方法的系統(tǒng)實現(xiàn)即super里面的方法即可。我們需 要攔截touch event時,在pointInside: withEvent里面返回YES,但不做處理可達到攔截的效果。需要注意的是,我們永遠都不應該retain UIEvent,UIEvent是存儲在event queue里面的,會循環(huán)利用,如果非得暫存某些狀態(tài),請將UIEvent的proterties拷貝然后使用NSDictionary等存儲。