iOS

Event Delivery & Responder

2019-08-14  本文已影响0人  ienos

三大事件

触摸事件、传感事件、远程控制事件

六种手势识别器

点击、拖拽、滑动、缩放、旋转、长按

UITouch & UIEvent

响应者对象 UIResponder

响应链上的响应者会同时处理触摸事件,能够在多个 view 内打印出 touchBegan:withEvent:

// 触摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

// 传感器事件
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;

// 远程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;

与加速计、陀螺仪和磁力计相关的运动事件不遵循响应者链,Core Motion 会将这些事件直接传递给我们指定的对象

事件的产生和传递

如何寻找一个合适的 View ?

alpha=0、子视图超出父视图、userInteractionEnabled=NO、hidden=YES 这四种情况下 hitTest:withEvent: 不会调用

hitTest:withEvent: & pointInside:withEvent:

// 返回视图层级中能响应触控点的最深视图
// point是该视图的坐标系上的点
- (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]) return nil;
    // 3.从后往前遍历自己的子控件,看是否有子控件更适合响应此事件
    int count = self.subviews.count;
    for (int i = count - 1; i >= 0; i--) {
        UIView *childView = self.subviews[i];
        CGPoint childPoint = [self convertPoint:point toView:childView];
        UIView *fitView = [childView hitTest:childPoint withEvent:event];
        if (fitView) {
            return fitView;
        }
    }
    // 没有找到比自己更合适的view
    return self;
}
// 返回视图是否包含指定的某个点,返回 YES 向所有当前视图的子视图发送 hitTest:withEvent
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;

事件的响应

响应者(Responder): 继承 UIResponder 的对象称为响应者对象
响应者链条(Responder Chain): 很多响应者链接在一起组合起来的一个链条称为响应者链(View -> SuperView -> ViewController -> UIWindow -> UIApplication -> AppDelegate)

处理者

找到 Responder 之后,如果 Responder 没处理,事件会被传递,会在 Responder Chain 下一个事件处理者,如果每一个 Responder 都不处理,则事件会被丢弃

上一篇 下一篇

猜你喜欢

热点阅读