今天仔細看了一下UIView和UIResponder的介紹,着重看了一下hitTest的介紹。
首先是官方的:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
1.我們都知道,一個屏幕事件由響應鏈一步步傳下去。這個函數返回的view就是可以讓你決定在這個point的事件,你用來接收事件的view。當然,如果這個point不在你的view的范圍,返回nil。
2.這個函數忽略userInteractionEnabled,hidden,alpha<0.01,也就是你一個view隱藏或什么了,還是可以作為接收者。
3.調用次序是從subview top到bottom,包括view本身。
到底有什么用呢?這里舉個例子:比如你的一個view,叫myMapView上面有一個系統MKMapView,但不想這個MKMapView允許滾動捏合等操作,所以設置它
userInteractionEnabled = NO,但是又想接收點擊事件,所以你重寫
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event ,這時會發現根本沒有調用,而是調用了touchesCancel,因為userInteractionEnabled = NO了,所以不能算正常完成touch事件。
這時你就可以重寫這個hitTest,如下:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if( CGRectContainsPoint(mkMapView.frame ,point))
{
return mkMapView;
}
return [super hitTest:point withEvent:event];
}
這樣,mkMapView仍然可以接收touchesEnded事件進行單擊處理。
最后補充一下UIResponder的事件順序,首先必須先調用hitTest判斷接收事件的view,如果hitTest返回的view不為空,則會把hitTest返回的view作為第一響應者,然后調用
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
如果有UIGestureRecognizer或者userInteractionEnabled這種優先級高的,就調用
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
否則,如果中間手指移動什么的,就調用
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;(移出當前view了,就不touchesEnded了,又touchesCancelled)
最后正常完成事件,就調用-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event。