iOS事件响应机制总结

事件分类

1. 高级事件:控件的点击事件/手势
2. 低级事件:触摸事件

响应流程:

1. 当发生一个触摸事件的时候,系统会把它打包成UIEvent对象,放到由UIApplication管理的一个事件队列里面
2.  等到合适的时机(runloop的运行循环有关),UIApplication会从队头取出一个事件,交给UIWindow对象去处理
3. UIWindow会在视图层级结构中找到最合适的视图让其去处理这个事件
    1. window会选中交给离自己最近的视图
    2. 调用该视图的-(UIView *)hitTest CGPoint(point) :withEvent(UIEvent *)event方法
        * 方法逻辑
            1. 判断当前视图是否可以传递事件,以下有任一条件满足进入2,否则返回nil
                * 视图.userInteractionEnabled   = YES
                * 视图.hidden = NO
                * 视图.alpha>0.01
            2. 判断视图是否在触摸点范围内:通过-(BOOL)pointInSide CGPoint(point) :wihtEvent(UIEvent *)event,返回yes进入3,否则返回nil
            3.遍历当前视图的子视图
                * 通过:[self convertPoint:point toView:视图.subviews[i]] 
                * 给子视图调用hitTest方法,返回一个fitView
                * 如果第2步返回的fitView为真的话,就return 该fitView,否则返回nil
            4. 子视图中没有找到退出了循环,返回self,自己就是hitTestView

代码演示

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    if (!self.userInteractionEnabled||self.hidden==YES||self.alpha<0.01) {
        return nil;
    }
    if (![self pointInside:point withEvent:event]) {
        return nil;
    }
    for (int i = 0; i<self.subviews.count; i++) {
        UIView *childView = self.subviews[i];
        CGPoint childPoint = [self convertPoint:point toView:childView];
        if ([childView hitTest:childPoint withEvent:event]) {
            return childView;
        }
    }
    return self;
}

处理事件

1. 前提
    * 重写了UIResponse的touch系列方法
        **touch系列方法中touchbegin一点要调用**
    * button的addtarget
    * textField的becomFirstResponser
2. nextResponser
    * 当前视图是一个普通view,nextResponser就是其父view
    * 当前视图是一个控制器的view, nextResponser就是其控制器但是如果想要在viewDidLoad方法中打印出view的nextResponser是行不通,因为这个方法调用时间比较早,座椅可以推迟一些时间

拦截事件

* 在UIApplication中拦截,事件就不会被分发下去,重写其sendEvent方法,实现事件的过滤
* 在离他最近的父view中也可以,重写hitTest::方法

事件处理顺序

1. view-fatherView->fatherViewController->window->UIApplication->UIApplelegate->废弃

猜你喜欢

转载自blog.csdn.net/li15809284891/article/details/76899467