• iOS中touch事件传递(响应者链)


    前言:

    不知不觉开发iOS三年之多了,成功的从一个小菜鸟变成了大菜鸟,前些日子面试被问到: iOS中事件传递是怎么样的,touch事件苹果是如何收集的?   由于之前没有了解过这些原理以及实现.一直本着能用就行.遇到这种问题直接懵逼了.

    后来通过阅读相关文章简单总结了一下,希望可以帮助到更多同学!!!希望共同成长

    在iOS中凡是继承自UIResponder的对象都能够接收并处理事件

    先说如何会产生touch事件

    1.触摸事件(例如点击,滑动,缩放等)

    2.加速计事件(例如摇微信一摇,指南针等)

    3.远程控制事件(例如蓝牙,wifi)

    1.触摸事件:

    当手指触摸手机屏幕时,系统会调用view的

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法

    当手指在手机屏幕上移动时,系统会调用view的

    -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法

    当手指离开手机屏幕时,系统会调用view的

    -(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event方法

    每个方法中的touches参数是NSSet类型(也就是集合类型),里边存放的是一个或多个UITouch对象,当手指触摸到屏幕时候会创建UITouch对象(一个手指对应一个UITouch对象),每个UITouch对象中存放的是这个动作的相关信息(触摸次数,视图大小,位置,类型等相关信息)

    当手指离开屏幕后,集合里保存的UITouch对象也会随之销毁.

    那我们来看看这些动作是怎么实现的,首先我们来看事件是怎么传递的

    发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的队列事件中,UIApplication会从事件队列中取出最前边的事件分发下去处理,会先发生给窗口视图KeyWindow

    视图会一层一层向上寻找最合适的视图来处理事件.找到合适的视图后会调用该视图的Touch方法(也就是上边说到的touchBegin,touchMove等)去做处理.也就是说该事件传递是从父视图依次向子视图传递的.如果父视图不能够接收并处理事件,那么他的子视图就不能接收并响应事件.

    以下几种情况View不能接收并响应事件

    1.view.userInteractionEnabled = NO;(不可交互)

    2.view.hidden = YES;(隐藏)

    3.view.alpha <=0.01;(透明度小于等于0.01)

    那么如何找到最合适的视图?

    1.自己本身是否可以接收事件

    2.触摸点是否在本身范围内

    3.查看自己的子控件是否可以接收事件

    4.查看触摸到是否在自己的子控件上

    5.如果没有就在自己本身处理

    - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 这个方法就是用来查找最合适处理事件的方法,和-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event配合使用(判断触摸到是否在自身上).

    通过上边的步骤.我们可以自己来模拟一下寻找view的实现

     

    最后总结来说一次完整的触摸事件的传递响应过程为:

    UIApplication-->UIWindow-->递归找到最合适处理的控件-->控件调用touches方法-->判断是否实现touches方法-->没有实现默认会将事件传递给上一个响应者-->找到上一个响应者-->找不到方法作废

    最后我们还可以使用响应者链找到当前视图

    - (UIViewController *)parentController

    {

        UIResponder *responder = [self nextResponder];

        while (responder) {

            if ([responder isKindOfClass:[UIViewController class]]) {

                return (UIViewController *)responder;

            }

            responder = [responder nextResponder];

        }

        return nil;

    }



     

  • 相关阅读:
    十三、asp.net中Repeater控件用法笔记
    九、chart控件的使用(图表数据的展示)
    一、在开发数据同步系统中的开发问题:
    ubuntu编译最新版本WebKit
    android apk 防止反编译技术第四篇-对抗JD-GUI
    小菜学Chromium之OpenGL学习之二
    webkit浏览器常见开发问题
    Android图片开发内幕--基础篇
    【转载】Android Metro风格的Launcher开发系列第二篇
    world 替换+正则表达式命令
  • 原文地址:https://www.cnblogs.com/baxiu/p/9336244.html
Copyright © 2020-2023  润新知