由Nil-Targeted Actions说起

作者: 2d899c5242bd | 来源:发表于2017-09-25 00:22 被阅读47次

    在开发中,做用户交互最常用的就是target-action 模式了。但是如果target的传入参数为nil会怎样呢?

    Apple 在UIContro.h里给出了说明:

    // passing in nil as the target goes up the responder chain. The action may optionally include the sender and the event in that order
    - (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
    

    什么是响应者
    应用程序用来接收和响应事件的对象就是响应者。在UIKit中其代码表现为UIResponder或其子类的实例对象。


    什么是响应者链?
    响应者链,是一条抽象链条,该链条的每个节点都是一个响应者。是通过UIResponder一个属性串联起来的

     @property(nonatomic, readonly) UIResponder *nextResponder; 
    

    注意: UIResponder 中该属性默认返回Nil。

    不过,UIKit中UIResponder子类已经给出了一个默认实现

    App中的默认响应者链
    • 响应链的意义:在第一响应者不处理该事件的时候,将其传递个下一个响应者,直到事件被处理或因响应链结束没有处理而被丢弃。
    • 传递是怎么进行的?
    //触摸类事件
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
    - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
    - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
    - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
    - (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);
    
    //3D touch类型
    - (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
    - (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
    - (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
    - (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
    
    //运动类型
    - (void)motionBegan:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
    - (void)motionCancelled:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
    ...
    

    什么是第一响应者
    UIKit认为处理当前事件最合适的那个响应者就是第一响应者。所以会出现针对不同事件当前第一响应者不同的情况。比如:触摸事件的第一响应者就是触摸发生的那个视图;摇晃手势的第一响应者是用户或者是UIKit指定的那个响应者。

    注意:运动型事件(比如:摇晃运动)不会使用响应者链传递机制,而是直接调用已经指定好的第一响应者。


    响应链条的应用:优雅的关闭键盘

    Mac Guru Sean Heber taught us how:
    [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];
    — Sean Heber (@BigZaphod) August 1, 2012


    说回问题:
    target 为nil的情况下,UIKit会先去找已经指定的第一响应者;如果没有,则调用用户触摸的视图。如果事件没有处理则沿着响应者链往下传递。


    参考链接:

    1. https://www.cocoanetics.com/2012/09/the-amazing-responder-chain/
    2. https://developer.apple.com/documentation/uikit/understanding_event_handling_responders_and_the_responder_chain?language=objc

    相关文章

      网友评论

        本文标题:由Nil-Targeted Actions说起

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