[ios2] UIView的hitTest,pointInside方法详解【转】

       关于UIView的触摸响应事件中,这里有一个常常容易迷惑的方法hitTest:WithEvent。先来看官方的解释:This method traverses the view hierarchy by sending the pointInside:withEvent: message 

to each subview to determine which subview should receive a touch event. 

If pointInside:withEvent: returns YES, then the subview’s hierarchy is traversed;
 otherwise, its branch of the view hierarchy is ignored.

 You rarely need to call this method yourself, 

but you might override it to hide touch events from subviews.(通 过发送PointInside:withEvent:消息给每一个子视图,这个方法遍历视图层树,来决定那个视图应该响应此事件。如果 PointInside:withEvent:返回YES,然后子视图的继承树就会被遍历;否则,视图的继承树就会被忽略。你很少需要调用这个方法,仅仅 需要重载这个方法去隐藏子视图的事件)。从官方的API上的解释,可以看出 hitTest方法中,要先调用 PointInside:withEvent:,看是否要遍历子视图。如果我们不想让某个视图响应事件,只需要重载 PointInside:withEvent:方法,让此方法返回NO就行了。不过从这里,还是不能了解到hitTest:WithEvent的方法的用 途。

         下面再从”Event Handling Guide for iOS”找答案,Your custom responder can use hit- testing to find the subview or sublayer of itself that is "under” a touch, and then handle the event appropriately。从中可以看出hitTest主要用途是用来寻找那个视图是被触摸了。看到这里对hitTest的调用过程还是一知半解。我们可以实际建立一个工程进行调试。建立一个MyView里面重载hitTest和pointInside方法:

  1. - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event{  
  2.   
  3. [super hitTest:point withEvent:event];  
  4.   
  5. return self;  
  6.   
  7. }  
  8.   
  9. - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{  
  10.   
  11.     NSLog(@"view pointInside");  
  12.   
  13.     return YES;  
  14.   
  15. }  

然后在MyView中增加一个子视图MySecondView也重载这两个方法  

  1. - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event{  
  2.   
  3. [super hitTest:point withEvent:event];  
  4.   
  5. return self;  
  6.   
  7. }  
  8.   
  9. - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{  
  10.   
  11.     NSLog(@"second view pointInside");  
  12.   
  13.     return YES;  
  14.   
  15. }  

        这里注意[super hitTest:point withEvent:event];必须要包括,否则hitTest无法调用父类的方法,这样就没法 使用PointInside:withEvent:进行判断,那么就没法进行子视图的遍历。当去掉这个语句的时候,触摸事件就不可能进到子视图中了,除非 你在方法中直接返回子视图的对象。这样你在调试的过程中就会发现,每次你点击一个view都会先进入到这个view的父视图中的hitTest方法,然后 调用super的hitTest方法之后就会查找pointInside是否返回YES如果是,则就把消息传递个子视图处理,子视图用同样的方法递归查找 自己的子视图。所以从这里调试分析看,hitTest方法这种递归调用的方式就一目了然了。

原文地址:https://www.cnblogs.com/jinjiantong/p/3056561.html