UIResponder 是iOS中用于处理各种类型事件的基类,继承自底层类 NSObject,而所有能响应事件的控件都继承自 UIResponder(UIView,UIViewController....)。
image.png
当我们在控件上物理操作某种事件时,UIResponder会识别到我们的操作事件并解析成能对应的事件类型,再找到能处理事件的响应对象对事件进行处理,事件的识别传递过程既为iOS中响应链的形成分为两大块:
1:事件分发(hit-Testing):设备识别到我们的物理事件时会形成响应的事件对象Event, 并通过 HitTest工具去查找到能执行该Event的载体,并激活等待执行,这个过程称为事件分发过程。
获取到Event后,系统Application 会从事件队列中按照先进先出原则取出一个事件对象,HitTest会首先检测该Event 下面的视图能否满足执行该Event的各种条件,如果满足就继续遍历该视图的subviews 直到找到最后一个满足条件的视图控件(既再没有子视图的那个控件),如果最终没有找到对应控件,则会回归到自身。
UIView 主要通过这两个方法来确定是否包含事件,以及查找事件对象:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
}
2:事件传递:事件产生时会🉐一个对应的初始对象,但是这个初始对象不一定能够处理该事件,这种情况下就会将事件继续往上层父视图传递,依次查找如果直到最上层窗口->application, 还是没能将该事件处理完,则该事件会被丢弃。
事件分发和事件传递是两个相反的顺序,分发的时候找到并激活最后一个满足Event条件的视图,往子视图一层层一直找到不满足条件的为止。事件传递是往父视图层层往上找,就近原则找到最先的能执行事件的视图时,事件传递立马终止。
UIResponder 中通过 nextResponder 方法来传递事件, 但要注意的是该方法默认返回都为nil, iOS UIview 系列控件中往上追溯父视图时都重写了 该方法,将返回的下一级响应者设置为了该控件的父视图。
UIResponder 中有一些方法用来控制响应链的传递:
open class UIResponder : NSObject, UIResponderStandardEditActions {
//指定下级响应者
open var next: UIResponder? { get }
//设置该对象能成为第一响应者
open var canBecomeFirstResponder: Bool { get } // default is NO
// default is NO
//设置该对象成为第一响应者,成为第一响应者能优先处理事件
open func becomeFirstResponder() -> Bool
//是否能取消第一响应者身份
open var canResignFirstResponder: Bool { get } // default is YES
// default is YES
//取消第一响应者身份
open func resignFirstResponder() -> Bool
//************触摸事件****
//判断该对象是否是第一响应者
open var : Bool { get }
open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)//点击时会调用
open func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) //监测手指移动
open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)//手指抬起
open func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?)//中断
//**********响应深按事件的方法****
@available(iOS 9.1, *)
open func touchesEstimatedPropertiesUpdated(_ touches: Set<UITouch>)
@available(iOS 9.0, *)
open func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?)
@available(iOS 9.0, *)
open func pressesChanged(_ presses: Set<UIPress>, with event: UIPressesEvent?)
@available(iOS 9.0, *)
open func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?)
@available(iOS 9.0, *)
open func pressesCancelled(_ presses: Set<UIPress>, with event: UIPressesEvent?)
//**********响应运动事件的方法****
@available(iOS 3.0, *)
open func motionBegan(_ motion: UIEventSubtype, with event: UIEvent?)
@available(iOS 3.0, *)
open func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?)
@available(iOS 3.0, *)
open func motionCancelled(_ motion: UIEventSubtype, with event: UIEvent?)
}
网友评论