美文网首页
响应者链条

响应者链条

作者: AYuan_ | 来源:发表于2016-03-26 19:15 被阅读46次

** 响应者链条**


屏幕快照 2016-03-26 下午6.38.21.png
  • 在iOS中不是任何对象都能处理时间,只有继承了UIResponder的对象才能接收并处理事件。我们称之为“响应者对象”
  • UIApplication UIViewController UIView都是继承自UIResponder,因此他们都是响应者对象,都能够接收并处理事件。
  • 当用户点击按钮,系统最先响应这个点击事件,由AppDelegate接收,然后不断上抛直到到达UIButton,如图中实线所示。当UIButton接收到这个事件,UIResponder相应的方法开始工作,系统默认做法是调用控件对应的super方法,值得一提的是:super会调用父类中的方法,而此处刚好会调到当前控件父控件所对应的方法。此时的事件传递方向刚好相反,从UIButton向底层抛,直到系统接收并做出响应,如图中虚线所示。这一来一回,我们称之为响应者链条。
  • 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中。UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow)。主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步。找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理。

UIView不接收触摸事件的三种情况

  • 不接收用户交互
    userInteractionEnabled = NO;
  • 隐藏
    hidden = YES;
  • 透明
    alpha = 0.0 ~ 0.01;
    如果一个控件的父控件隐藏了,则子控件也将被隐藏

UIResponder内部提供了以下方法来处理事件

屏幕快照 2016-03-26 下午6.46.49.png
  • UIView中的方法
    继承关系:UIWindow\UIButton -> UIView -> UIResponder -> NSObject
    上文中响应者链条提到过,系统接收用户点击事件后会将事件不断上抛,直到到达UIButton,那么这中间又是那些东西在运作?
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event ;
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

这两个不太常见的方法其实是属于UIView的。

如何找到最合适的控件来处理事件

  • 流程

    • 判断当前控件userInteractionEnabled、hidden、alpha这三个属性的值( 自己是否能接收触摸事件)
    • 调用 pointInside: withEvent: ( 触摸点是否在自己身上)
    • 从后向前遍历子控件,并调用子控件的 hitTest: withEvent: 和 pointInside: withEvent: 方法(从后往前遍历子控件,重复前面两个步骤(遍历子控件时,先取出最后添加的那个子控件(因为在最前面))
  • 代码

    • hitTest和point方法
/*在AppDelegate中自定义UIWindow*/
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    //自定义window
    self.window = [[LTYWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor redColor];
    //加载storyboard
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    
    //加载箭头指向的控制器
    UIViewController *vc = [storyboard instantiateInitialViewController];
    
    //设置窗口的根控制器
    self.window.rootViewController = vc;
    
    [self.window makeKeyAndVisible];
    
    return YES;
}
/**
调用事件:当事件传递给控件的时候,就会调用控件的这个方法,去寻找最合适的view
作用:寻找最合适的view
point:当前的触摸点,point这个点的坐标系就是方法调用者
*/
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    //调用系统的做法取寻找最合适的view,返回最合适的view
    UIView *fitView = [super hitTest:point withEvent:event];
    NSLog(@"%s-----%@",__func__,fitView);
    return fitView;
}
/**作用:判断当前这个点在不在方法调用者(控件)上*/
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    return YES;
}

  • 事件的产生和传递
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"%@",[self class]);
}

//UIApplication -> [UIWindow hitTest:wthTest:withEvent:] -> [subView hitTest:wthTest:withEvent:]
//因为所有的视图类都是继承BaseView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    //1.判断当前控件能接收事件
    if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
 
    //2.判断点在不在当前控件
    if ([self pointInside:point withEvent:event] == NO) return nil;
    
    //3.从后往前遍历自己的子控件
    NSInteger count = self.subviews.count;
    for (NSInteger i = count - 1; i>=0; i--) {
        UIView *childView = self.subviews[i];
        //把当前控件上的坐标系转换成子控件上的坐标系
        CGPoint childP = [self convertPoint:point toView:childView];
        UIView *fitView = [childView hitTest:childP withEvent:event];
        if (fitView) { //寻找最合适的view
            return fitView;
        }    
    }
    //循环结束,表示没有比自己更适合的view
    return self;
}

相关文章

  • 响应者链

    1> 什么是响应者链 响应者链条是由多个响应者对象连接起来的链条,其中响应者对象是能处理事件的对象,所有的View...

  • 什么是响应者链

    响应者链条是由多个响应者对象连接起来的链条,其中响应者对象是能处理事件的对象,所有的View和ViewContro...

  • 响应者链条

    1.什么是事件响应链2.touch 事件分发3.hit-test 底层实现4.应用 1.什么是事件响应链 大多数事...

  • 响应者链条

    什么是事件? iOS中事件分为3大类 : 触摸事件, 加速计事件和远程控制事件.当你的手指在手机屏幕上触摸时, 产...

  • 响应者链条

    响应者链条:是由多个响应者对象连接起来的链条 作用:能很清楚的看见每个响应者之间的联系,并且可以让一个事件多个对象...

  • 响应者链条

    ** 响应者链条** 在iOS中不是任何对象都能处理时间,只有继承了UIResponder的对象才能接收并处理事件...

  • 响应者链条

  • 响应者链条

    简单来说就是 :一级一级的找到响应的视图,如果没有就传给UIWindow实例和UIApplication实例,要是...

  • 响应者链条

    所有控件的多点触摸默认是关闭的。需要使用多点触摸时要手动打开。 UIView的属性:保存是否打开多点触摸的属性 @...

  • 响应者链条

    响应者链条 一、触摸事件处理的详细过程 用户点击屏幕后产生的一个触摸事件,经过一些列的传递过程后,会找到最合适的视...

网友评论

      本文标题:响应者链条

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