响应链

Philm首页的拍摄按钮与滤镜是重叠的,且层级关系为拍摄按钮需要显示在最上层,同时要求滤镜可以滑动.这就需要使用响应链来处理重叠部分的响应顺序问题.

当发生触摸事件时,hitTest会检查触摸点所在位置,并从最底层开始,递归找出当前所有的响应器,记录为responder chain,并找出层级在最上方的view作为第一响应者.

所以当前的响应器链为: UIKit –> active app’s event queue –> window –> root view —> vc.view — > 滤镜view—>拍摄按钮view.其中 最上层的拍摄按钮为当前的第一响应者.

如果这个hit-test找出的这个view不能处理事件,那么UIKit会从响应器链中寻找nextResponder,这个responder可以决定响应事件还是继续寻找nextResponder.以此类推,直到找到可以响应的responder或者响应链全部被查找完.通过这个原理,处理上述问题的解决方案是:使拍摄按钮的view不响应触摸事件,而是传递给下层的滤镜view. 以下为具体代码:

//图层穿透
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *hitView = [super hitTest:point withEvent:event];
if(hitView == self)
{
return nil;
}
return hitView;
}

另外通过响应链,我们也可以寻找当前最上层的controller,这样在view层也可以实现push/present或其他controller才能做的操作而不需要使用代理/block一层层传递.