美文网首页
响应者链

响应者链

作者: noprkl | 来源:发表于2016-09-29 22:27 被阅读0次
    什么是响应者链

    在iOS的事件传递过程中需要通过多个响应者来寻找最合适的事件接收者,把这个过程中的响应者串联起来就是响应者链。

    事件的产生和传递过程

    当系统检测到触摸事件event发生的时候,将event放入当前活动的UIApplication事件队列中,UIApplication会从队列中取出event传递给主窗口UIWindow(keyWindow)keyWindow会通过递归找到合适的View,调用touches;

    触摸事件event——>UIApplication队列——>UIWindow对列接收——>keyWindow递归找到View——>View调用合适的touches——>处理事件

    递归寻找响应者 (hitTest:withEvent:和pointInside:withEvent:)
    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        NSLog(@"%@-hit-%@", NSStringFromClass(self.class), event);
        // 1.判断能否接受点击事件
        if (!self.userInteractionEnabled || self.alpha == 0.0 || self.hidden) {
            return nil;
        }
        // 2.判断点是否点击在当前视图上
        if (![self pointInside:point withEvent:event]) {
            return nil;
        }
        // 反向遍历子视图
        __block UIView *fitView = nil;
        [self.subviews.reverseObjectEnumerator.allObjects enumerateObjectsUsingBlock:^(UIView *childView, NSUInteger idx, BOOL * _Nonnull stop) {
            // 把当前坐标系上的点转换成子控件上的点
            CGPoint chidlPoint = [self convertPoint:point toView:childView];
            // 判断这个点上是否在子视图上,找到第一个响应视图
            fitView = [childView hitTest:chidlPoint withEvent:event];
            if (fitView) {
                *stop = YES;
            }
        }];
        if (fitView) {
            return fitView;
        }
        return self;
    }
    
    寻找合适的响应者

    如果响应者处理不了touches事件,会将事件上移,该类的上一级如果是UIView,子视图处理事件,处理不了,寻找它的父视图
    该类的上一级如果是UIViewController,则是由它所属的控制器处理
    事件上移到最顶层如果处理不了,把事件传递给UIWindowUIWindow处理不了给UIApplicationUIApplication默认不响应,这个touches就会被吃掉

    寻找当前view的UIViewController

    思路:
    根据响应者链寻找,找到相应当前view事件的控制器
    1.给当前控制器添加一个导航条 ‘nav’ 是window的rootViewController

    UIViewController *vc = ((AppDelegate *)[UIApplication sharedApplication].delegate).nav.visibleViewController;
    

    2.通过遍历当前view的响应者链 找到 View所属的控制器

    - (UIViewController *)viewController:(UIView *)view
        for (UIView *next = view; next; next = next.superview) {
            UIResponder *responder = [next nextResponder];
            if ([responder isKindOfClass:[UIViewController class]]) {
                return (UIViewController *)responder;
            }
        }
        return nil;
    }
    

    相关文章

      网友评论

          本文标题:响应者链

          本文链接:https://www.haomeiwen.com/subject/pjdlyttx.html