MST

星途 面试题库

面试题:Objective-C自定义控件的事件传递机制与响应链原理

详细阐述Objective-C中自定义控件的事件传递机制,当一个触摸事件发生在自定义控件上,系统如何确定哪个视图应该响应这个事件?响应链的具体流程是什么?如果自定义控件内部有多个子视图,如何控制事件的传递与响应?
43.2万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

1. 事件传递机制概述

在Objective-C中,当触摸事件发生时,系统会从应用程序的主窗口开始,按照一定的规则寻找最合适的视图来处理这个事件。这个过程基于视图的层级关系以及视图的属性(如是否可交互、是否隐藏、透明度等)。

2. 确定响应视图的规则

  1. 窗口首先接收事件:应用程序的主窗口是事件传递的起点。UIWindow会将事件传递给它的rootViewController的视图。
  2. 视图层级遍历:系统会从父视图开始,递归地询问每个子视图是否能够处理该事件。询问的依据主要是hitTest:withEvent:方法。该方法首先判断自身是否能接收触摸事件(通过userInteractionEnabled是否为YEShidden是否为NOalpha是否大于0.01等条件),如果不能则直接返回nil。如果能接收,会遍历它的子视图,从后往前(即最上层的子视图先被询问)调用子视图的hitTest:withEvent:方法。如果某个子视图返回非nil,则该子视图就是最合适的视图,否则自身就是最合适的视图并返回自身。
  3. 最终确定响应者:通过上述遍历,最终会确定一个最合适的视图来响应事件,这个视图就是hitTest:withEvent:方法返回的视图。

3. 响应链流程

  1. 初始响应者:当触摸事件发生在自定义控件上,该自定义控件成为初始响应者。
  2. 向上传递:如果初始响应者不能处理该事件,它会将事件沿着响应链向上传递。响应链的顺序是:视图 -> 父视图 -> 视图控制器 -> 父视图控制器 -> … -> UIWindow -> UIApplication。
  3. 寻找处理者:沿着响应链,每个对象都有机会处理事件。如果某个对象能够处理事件,事件处理就会在这里结束。如果一直传递到UIApplication都没有对象处理事件,事件就会被忽略。

4. 自定义控件内多个子视图时控制事件传递与响应

  1. 重写hitTest:withEvent:方法:在自定义控件类中重写hitTest:withEvent:方法,可以根据业务需求自定义事件传递逻辑。例如,可以根据触摸点的位置在子视图间进行更精细的判断,或者根据某些条件直接返回特定的子视图。
  2. 设置子视图属性:通过设置子视图的userInteractionEnabled属性为NO,可以阻止子视图接收触摸事件,这样事件就会传递给自定义控件或其他符合条件的视图。
  3. 手势识别器:可以为子视图或自定义控件添加手势识别器(UIGestureRecognizer)。手势识别器可以在触摸事件传递到视图的touches方法之前捕获并处理事件,从而实现对事件的拦截和处理。例如,可以通过添加UITapGestureRecognizer来处理点击事件,并且可以设置手势识别器的代理方法,进一步控制事件的处理逻辑。