iOS深入理解事件传递及响应

一、事件传递

事件传递相关的两个方法

objectivec 复制代码
// 哪个视图响应事件返回哪个  
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;     
// 点击位置是否在当前视图范围  
-(BOOL)pointInside(CGPoint)point withEvent:(UIEvent *)event; 

如图,View A中包含View B1、View B2,View B2中包含View C1,View C2既包含View C1的一部分,又包含View B2的一部分,View C1中包含View D。当点击View C2的空白区域时,系统如何找到事件响应者为View C2?

(1)事件传递流程

当用户点击屏幕的某个位置,该事件会被传递给UIApplicationUIApplication又传递给当前的UIWindow,UIWindow会通过hitTest:WithEvent:方法返回响应的视图。hitTest:WithEvent:方法内部通过pointInside:withEvent:方法判断点击point是否在当前UIWindow范围内,如果在,则会遍历其中的所有子视图SubViews来查找最终响应此事件的视图,遍历方式为倒序遍历,即最后添加到UIWindow的视图最优先被遍历到,依次遍历,可以看作是递归调用。每个UIView中又都会调用其对应hitTest:WithEvent:方法,最终返回响应视图hit,如果hit有值,则hit视图就作为该事件的响应视图被返回,如果hit没有值,但在当前UIWindow范围内,则当前UIWindow作为事件的响应视图。

(2)hitTest:WithEvent:系统内部实现

首先在hitTest:WithEvent:方法内部先判断当前视图的hidden属性、是否可交互、透明度是否大于0.01。如果该视图不同时满足上述3个条件,则返回nil,当前视图不作为事件的响应视图,当前视图的父视图继续遍历其他的子视图;如果该视图没有隐藏、用户可交互、透明度大于0.01,则会通过pointInside:WithEvent:方法判断点击的点是否在当前视图范围内,如果不在,则同样返回nil,当前视图仍不作为事件的响应者;如果在,则会通过倒序遍历当前视图的子视图,调用其子视图对应的hitTest:WithEvent:方法,如果某个视图返回了事件响应视图,则该返回的视图被作为事件的响应者,反之则继续遍历判断。如果遍历完后没有任何视图响应此事件,因为此事件点击的范围在当前视图范围内,则将当前视图作为事件响应者返回。

二、视图事件响应

上述讲述了视图事件的传递流程,当视图事件传递后,最终事件由谁来响应呢,这就涉及视图的响应链、响应链的机制和流程。 如图,页面存在一个UILabel一个UITextField、一个UIButton,实线箭头表示下一个响应者。

视图事件响应链相关的方法

objectivec 复制代码
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

例如,当点击View C2的空白处时,事件由谁来响应呢?首先由View C2接收事件,如果它不处理,就会把事件传递给View B2,如果View B2还不响应这个事件,View B2会通过响应链将事件传递给它的父视图View A,如果还不响应,则会沿着响应链一直向上传递,直到传递到UIApplicationDelegate仍然不对事件进行处理,则会忽略此事件

相关推荐
RickeyBoy4 小时前
SwiftUI 如何实现 Infinite Scroll?
ios·面试
升鲜宝供应链及收银系统源代码服务6 小时前
《IntelliJ + Claude Code + Gemini + ChatGPT 实战配置手册升鲜宝》
java·前端·数据库·chatgpt·供应链系统·生鲜配送
i建模6 小时前
将Edge浏览器的标签页从顶部水平排列**移至左侧垂直侧边栏
前端·edge
跟着珅聪学java7 小时前
js编写中文转unicode 教程
前端·javascript·数据库
壹方秘境7 小时前
厌倦了那些看着像一个模版复刻出来的抓包工具,我开发了一款iOS端HTTPS抓包调试工具
ios·程序员·产品
英俊潇洒美少年7 小时前
Vue3 深入响应式系统
前端·javascript·vue.js
英俊潇洒美少年8 小时前
React 最核心 3 大底层原理:Fiber + Diff + 事件系统
前端·react.js·前端框架
我命由我123458 小时前
React Router 6 - 概述、基础路由、重定向、NavLink、路由表
前端·javascript·react.js·前端框架·ecmascript·html5·js
LJianK18 小时前
java封装
java·前端·数据库
yaaakaaang9 小时前
(四)前端,如此简单!---Promise
前端·javascript