在iOS系统中,一共有三种类型的Event, 分别是touch events, motion events和remote-control events。touch events是用户触摸屏幕时触发的事件,motion events是用户移动设备时触发的事件,remote-control events是用户通过配件触发的事件(如耳机等线控或锁频时线控等)。我们用的最多,交互最多的当然就是touch events了。
阅读开发文档Event Handling Guide for iOS这一章,知道产生touches时,系统会将一系列的touches打包到UIEvent里,该UIEvent存储在当前应用event queue里,然后dispatch queue里面的事件给当前的key window, window通过hitTest: withEvent方法找到能够接受该event的view。在最顶层次的View里调用hitTest: withEvent,然后该方法再调用自身的pointInside: withEvent方法来判断需不需要处理,如果pointInside: withEvent返回YES,则hitTest: withEvent遍历所有subview,返回能够消费这个event的view,否则的话自身处理。如果pointInside: withEvent返回NO,则沿着responder chain向super view或者view controller传递event。如果view能够消费touch event,则系统会向该responder 发送touchesBegan: touchesMoved: touchesCancelled: touchesEnded:等消息,然后来处理产生的touch events。touch的生命周期是跟它的hitTestView绑定的,就是从hitTestView接受该touch开始直到该touch消失都跟该hitTestView绑定。
所以我们需要自行处理touch event时,需要实现touchesBegan: touchesMoved: touchesCancelled: touchesEnded:等方法,如果不需要自行处理,或者是同时保留系统处理,则我们只需调用如上方法的系统实现即super里面的方法即可。我们需要拦截touch event时,在pointInside: withEvent里面返回YES,但不做处理可达到拦截的效果。需要注意的是,我们永远都不应该retain UIEvent,UIEvent是存储在event queue里面的,会循环利用,如果非得暂存某些状态,请将UIEvent的proterties拷贝然后使用NSDictionary等存储。