响应方法和响应事件传递

目录响应方法和响应事件传递事件处理机制的应用 使用Hit-Test来扩大点击范围处理兄弟控件的事件 事件处理机制在系统控件中 参考资料
事件的种类
【响应方法和响应事件传递】其中最常见的就是触摸事件,文章后续都已触摸事件为例来进行讲解 。
事件响应链
首先iOS只有集成了的对象,才有资格成为事件响应者 。常见的时间响应者对象包含、、、等组件 。其次,在App中的组件是一个树状结构,在每个单例下可能会有多个,一个下有可能有多个,以此类推,因此iOS中,会形成一个事件响应链的形态 。
事件响应者 如何成为事件响应者
只要是继承了的对象都可以成为事件响应者,但是一个事件产生之后第一件是是要找出这个事件的第一响应者 。找出第一响应者的方法叫做hit-test 。
Hit-Test
可以成为第一响应者的对象除了需要继承以外,还有一个更严格的条件,除对象以外,其余的对象如果想要成为第一响应者一定要继承,只有才有资格成为第一响应者 。
类中包含两个方法
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;// recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;// default returns YES if point is in bounds
第二个::方法仅在::方法中才会调用 。
找到事件的第一响应者的流程如下:
系统在检测到用户的触摸事件后,将事件以及时间的参数(比如触摸点的坐标)等数据作为参数,向当前的单例对象发送消息 。单例收到之后,会依次调用显示的对象的::方法,如果方法返回了一个对象,则这个对象就是第一响应者,如果返回为空,则对象就是第一响应者 。在::方法中,会调用::方法来判断该事件是否属于当前对象,如果不属于,就直接返回空 。如果属于当前对象,则会继续遍历其,调用每个的::方法 。如果所有该方法都返回了空,那么就返回当前对象为第一事件响应者 。以此类递归找到最终的子组件,这样就可以找到第一事件响应者了 。

响应方法和响应事件传递

文章插图
响应方法和响应事件传递
类中包含如下的方法:
// 下一个响应者open var next: UIResponder? { get }// 第一响应者相关方法open var canBecomeFirstResponder: Bool { get } // default is NOopen func becomeFirstResponder() -> Boolopen var canResignFirstResponder: Bool { get } // default is YESopen func resignFirstResponder() -> Boolopen var isFirstResponder: Bool { get }// 触摸事件open func touchesBegan(_ touches: Set, with event: UIEvent?)open func touchesMoved(_ touches: Set, with event: UIEvent?)open func touchesEnded(_ touches: Set, with event: UIEvent?)open func touchesCancelled(_ touches: Set, with event: UIEvent?)@available(iOS 9.1, *)open func touchesEstimatedPropertiesUpdated(_ touches: Set)// 运动事件open func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?)open func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?)open func motionCancelled(_ motion: UIEvent.EventSubtype, with event: UIEvent?)// 远程控制事件open func remoteControlReceived(with event: UIEvent?)// 按压事件open func pressesBegan(_ presses: Set, with event: UIPressesEvent?)open func pressesChanged(_ presses: Set, with event: UIPressesEvent?)open func pressesEnded(_ presses: Set, with event: UIPressesEvent?)open func pressesCancelled(_ presses: Set, with event: UIPressesEvent?)