-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (!self.isUserInteractionEnabled || self.hidden || self.alpha<=0.01) {
return nil;
}
CGRect touchRect = CGRectInset(self.bounds, -20, -20);
if (CGRectContainsPoint(touchRect, point)) {
for (UIView *subView in [self.subviews reverseObjectEnumerator]) {
CGPoint convertedPoint = [subView convertPoint:point toView:self];
UIView *hitTestView = [subView hitTest:convertedPoint withEvent:event];
if (hitTestView) {
return hitTestView;
}
}
return self;
}
return nil;
}
二、穿透传递事件。
假设有两个view,viewA和viewB,viewB完全覆盖viewA,我们希望点击viewB时能响应viewA的事件。我们重写这个viewA的hitTest:withEvent:方法,不继续遍历它的子视图,直接返回自身。代码如下:
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
if (!self.isUserInteractionEnabled || self.hidden || self.alpha<=0.01) {
return nil;
}
if ([self pointInside:point withEvent:event]) {
NSLog(@"in view A");
return self;
}
return nil;
}
回调机制
在自定义控件开发中,需要向它的父类回传返回值。比如一个存放按钮的自定义控件,需要在上层接收按钮点击事件。我们可以使用多种方式回调消息,比如target action模式、代理、block、通知等。
Target-Action
Target-Action是一种设计模式,当事件触发时,它让一个对象向另一个对象发送消息。这个模式我们接触的比较多,如为按钮绑定点击事件,为view添加手势事件等。UIControl及其子类都支持这个机制。Target-Action 在消息的发送者和接收者之间建立了一个松散的关系。消息的接收者不知道发送者,甚至消息的发送者也不知道消息的接收者会是什么。
基于 target-action 传递机制的一个局限是,发送的消息不能携带自定义的信息。iOS 中,可以选择性的把发送者和触发 action 的事件作为参数。除此之外就没有别的控制 action 消息内容的方法了。
举个例子,我们使用Target-Action为控件添加一个单击手势。
UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(refresh)];
[_imageView addGestureRecognizer:tapGR];
- (void)refresh{
NSLog(@"Touch imageView");
}
代理
代理是一种我们常用的回调方式,也是苹果推荐的方式,在系统框架UIKit中大量使用,如UITableView、UITextField。
优点:1,代理语法清晰,可读性高,易于维护 ;2,它减少了代码耦合性,使事件监听与事件处理分离;3,一个控制器可以实现多个代理,满足自定义开发需求,灵活性较高;
缺点:1,实现代理的过程较繁琐;2,跨层传值时加大代码的耦合性,并且程序的层次结构也变得混乱;3,当多个对象同时传值时不易区分,导致代理易用性大大降低;










