iOS学习笔记【二】——事件处理

iOS学习笔记【二】——事件处理

只做简单笔记📝 详细请戳标题链接🔗

key point:iOS把用户触发事件打包成一个UIEvent对象,作为事件传递的消息载体,放入当前活跃的APP的消息队列中,然后通过Hit-Testing来找到响应者,响应者通过响应链的传递做出响应。

系统响应阶段

触摸事件从触屏产生后,由IOKit生成一个 IOHIDEvent 事件,并传递给SpringBoard,再由SpringBoard通过 mach port 转发给App 进程。
主线程的runloop被唤醒,触发了source1回调。source1回调又触发了一个source0回调,source0回调将接收到的IOHIDEvent对象封装成UIEvent对象,此时APP将正式开始对于触摸事件的响应。

UIEvent

UIEvent包含最常见的三种事件:Touch Events(触摸事件)、Motion Events(运动事件,比如重力感应和摇一摇等)、Remote Events(远程事件,比如用耳机上的按键来控制手机)。

UIResponder响应者对象

在UIKit中,UIApplication、UIView、UIViewController这几个类是直接继承自UIResponder,所以这些类都可以接收并处理响应事件。UIResponder内部提供了以下方法来处理事件触摸事件:

 // 触摸事件
 - (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;

UITouch对象

  • 保存着跟手指相关的信息,比如触摸的位置、时间、阶段
  • 当手指移动时,系统会更新同一个UITouch对象,使之能够一直保存该手指在的触摸位置
  • 当手指离开屏幕时,系统会销毁相应的UITouch对象
  • 一根手指对应一个UITouch对象
  • 如果两根手指同时触摸一个view,那么view只会调用一次touchesBegan: withEvent:方法,touches参数中装着2个UITouch对象
触摸产生时所处的窗口
@property(nonatomic,readonly,retain) UIWindow *window;
触摸产生时所处的视图
@property(nonatomic,readonly,retain) UIView *view;
短时间内点按屏幕的次数,可以根据tapCount判断单击、双击或更多的点击
@property(nonatomic,readonly) NSUInteger tapCount;
返回值表示触摸在view上的位置,调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
(CGPoint)locationInView:(UIView *)view;
该方法记录了前一个触摸点的位置
(CGPoint)previousLocationInView:(UIView *)view;

响应链相关

// 下一响应者
- (UIResponder *)nextResponder;
// 判定对象是否是第一响应者
- (BOOL)isFirstResponder;
// 判断对象是否允许成为第一响应者 
- (BOOL)canBecomeFirstResponder; 
// 成为第一响应者 
- (BOOL)becomeFirstResponder;
// 判断对象是否允许放弃第一响应者
- (BOOL)canResignFirstResponder; 
// 放弃第一响应者 
- (BOOL)resignFirstResponder;

事件的传递

触摸事件的传递是从父控件传递到子控件,也就是UIApplication->window->寻找处理事件最合适的view,如果父控件不能接受触摸事件,那么子控件就不可能接收到触摸事件

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

  • 不允许交互:userInteractionEnabled = NO(UIImageView、UILabel默认为NO
  • 隐藏:如果把父控件隐藏hidden,那么子控件也会隐藏,隐藏的控件不能接受事件
  • 透明度:如果设置一个控件的透明度<0.01,会直接影响子控件的透明度。alpha:0.0~0.01为透明。

hitTest:withEvent:

  • 能否处理触摸事件
  • 触摸点是否在边界范围内:调用pointInside:withEvent:方法判断点在不在当前view上

传递过程

  • UIApplication接收到事件,将事件传递给keyWindow。
  • keyWindow遍历subViews的hitTest:withEvent:方法,找到点击区域内合适的视图来处理事件。
  • UIView的子视图也会从后往前遍历其subViews的hitTest:withEvent:方法,以此类推。
  • 直到找到点击区域内,且处于最上方的视图,将视图逐步返回给UIApplication。
  • 在查找第一响应者的过程中,已经形成了一个响应者链。
  • 应用程序会先调用第一响应者处理事件。
  • 如果第一响应者不能处理事件,则调用其nextResponder方法,一直找响应者链中能处理该事件的对象。
  • 最后到UIApplication后仍然没有能处理该事件的对象,则该事件被废弃。
    在这里插入图片描述

Q&A

  • 如何通过一个view查找它所在的viewController——响应链,nextResponder
  • 对于一个超出父View范围的子View,如何保证其响应事件——重写父视图的hitTest:withEvent:方法

先酱 后续补上手势识别的部分(TODO)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值