Event Delivery: The Responder Chain

一个事件都经历一个特殊的流程直到它被传给一个对象进行处理。首先,单例UIApplication对象从事件队列的顶部取出事件,并未处理它而进行分配。典型的是,UIApplication将事件送给window object(手机屏幕),window object将事件传给初始化对象进行处理,初始化对象决定了事件的类型。
事件类型分类:
Touch events(触屏事件):window object 首先将事件传给被触摸的视图,这个视图称为hit-test view,将找hit-test view的过程称为hit-testing,这个过程被描述为Hit-Testing Returns the View Where a Touch Occurred.
Motion and remote control events:这window object将运动事件或远端控制事件发送给first responder进行处理,这一过程描述为The Responder Chain Is Made Up of Responder Objects.

(1)Hit-Testing Returns the View Where a Touch Occurred
iOS 使用hit-Testing找出被触摸的view,Hit-testing包含检查是否一个触摸事件在所有相关的视图对象的范围内。如果在,hit-testing将递归的检查触摸事件发生的视图的所有子视图。在视图层次中最低的包涵触摸点的视图变为hit-test view。iOS决定了哪个是hit-test view后,就将触摸事件传给hit-test view进行处理。
例如:用户触摸了viewE,iOS将通过按顺序检查所有父视图来找hit-test view
1)触屏发生在A视图范围内,所以检查子视图B、C;
2)触屏没有发生在B视图内,但发生在A视图,因此检查子视图D、E
3)触屏没有发生在D视图内,但发生在A视图,视图E是包涵触屏事件的视图层次中的最低的视图,因此它变为hit-test view
Event Delivery: The Responder Chain_第1张图片
hitTest:withEvent:方法的处理流程如下:
首先调用当前视图的pointInside:withEvent:方法判断触摸点是否在当前视图内;(pointInside:withEvent:(该方法用来判断点击事件发生的位置是否处于当前视图范围内,以确定用户是不是点击了当前视图),如果pointInside:withEvent:返回YES,则继续逐级调用,直到找到touch操作发生的位置,这个视图也就是要找的hit-test view。)。若返回NO,则hitTest:withEvent:返回nil;若返回YES,则向当前视图的所有子视图(subviews)发送hitTest:withEvent:消息,所有子视图的遍历顺序是从最顶层视图一直到到最底层视图,即从subviews数组的末尾向前遍历,直到有子视图返回非空对象或者全部子视图遍历完毕;
若第一次有子视图返回非空对象,则hitTest:withEvent:方法返回此对象,处理结束;如所有子视图都返回非,则hitTest:withEvent:方法返回自身(self)。
***说明***
1、如果最终hit-test没有找到第一响应者,或者第一响应者没有处理该事件,则该事件会沿着响应者链向上回溯,如果UIWindow实例和UIApplication实例都不能处理该事件,则该事件会被丢弃;
2、hitTest:withEvent:方法将会忽略隐藏(hidden=YES)的视图,禁止用户操作(userInteractionEnabled=YES)的视图,以及alpha级别小于0.01(alpha<0.01)的视图。如果一个子视图的区域超过父视图的bound区域(父视图的clipsToBounds 属性为NO,这样超过父视图bound区域的子视图内容也会显示),那么正常情况下对子视图在父视图之外区域的触摸操作不会被识别,因为父视图的pointInside:withEvent:方法会返回NO,这样就不会继续向下遍历子视图了。当然,也可以重写pointInside:withEvent:方法来处理这种情况。
3、我们可以重写hitTest:withEvent:来达到某些特定的目的,下面的链接就是一个有趣的应用举例,当然实际应用中很少用到这些。
(2)The Responder Chain Is Made Up of Responder Objects
响应链(responder)由一系列响应对象组成,它开始于first responder,结束于application对象,如果first responder不能处理事件,it forwards the event to the next responder in the responder chain.响应者对象(Responder Object),顾名思义,指的是有响应和处理事件能力的对象。UIResponder是所有响应对象的基类,在UIResponder类中定义了处理上述各种事件的接口。我们熟悉的UIApplication、 UIViewController、和UIView都直接或间接的继承自UIResponder,所以它们的实例都是可以构成响应者链的响应者对象。(which means that all views and most key controller objects are responders. Note that Core Animation layers are not responders.)
first responder是被指定第一个去接受事件。一个对象通过做两件事可以成为 first responder:
1.重载canBecomeFirstResponder方法,并返回yes;
2.接受becomenfirstresponder的消息,必要时,一个对象可以向他自己发送这个消息。
******shouting****
vents are not the only objects that rely on the responder chain. The responder chain is used in all of the following:
* Touch events. If the hit-test view cannot handle a touch event, the event is passed up a chain of responders that starts with the hit-test view.
* Motion events. To handle shake-motion events with UIKit, the first responder must implement either the motionBegan:withEvent: or motionEnded:withEvent: method of the UIResponder class, as described in Detecting Shake-Motion Events with UIEvent.
* Remote control events. To handle remote control events, the first responder must implement the remoteControlReceivedWithEvent: method of the UIResponder class.
* Action messages. When the user manipulates a control, such as a button or switch, and the target for the action method is nil, the message is sent through a chain of responders starting with the control view.
* Editing-menu messages. When a user taps the commands of the editing menu, iOS uses a responder chain to find an object that implements the necessary methods (such as a target=”_self” cut:/a, a target=”_self” copy:/a, and a target=”_self” paste:/a). For more information, see Displaying and Managing the Edit Menu and the sample code project, a target=”_self” CopyPasteTile/a.
* Text editing. When a user taps a text field or a text view, that view automatically becomes the first responder. By default, the virtual keyboard appears and the text field or text view becomes the focus of editing. You can display a custom input view instead of the keyboard if it’s appropriate for your app. You can also add a custom input view to any responder object. For more information, see Custom Views for Data Input.
UIKit automatically sets the text field or text view that a user taps to be the first responder; Apps must explicitly set all other first responder objects with the becomeFirstResponder method.
(3)The Responder Chain Follows a Specific Delivery Path
If the initial object—either the hit-test view or the first responder—doesn’t handle an event, UIKit passes the event to the next responder in the chain. Each responder decides whether it wants to handle the event or pass it along to its own next responder by calling the nextResponder method.This process continues until a responder object either handles the event or there are no more responders.

The responder chain sequence begins when iOS detects an event and passes it to an initial object, which is typically a view. The initial view has the first opportunity to handle an event. Figure 2-2 shows two different event delivery paths for two app configurations. An app’s event delivery path depends on its specific construction, but all event delivery paths adhere to the same heuristics.

Figure 2-2 The responder chain on iOS
Event Delivery: The Responder Chain_第2张图片
For the app on the left, the event follows this path:

1.The initial view attempts to handle the event or message. If it can’t handle the event, it passes the event to its superview, because the initial view is not the top most view in its view controller’s view hierarchy.
2.The superview attempts to handle the event. If the superview can’t handle the event, it passes the event to its superview, because it is still not the top most view in the view hierarchy.
3.The topmost view in the view controller’s view hierarchy attempts to handle the event. If the topmost view can’t handle the event, it passes the event to its view controller.
4.The view controller attempts to handle the event, and if it can’t, passes the event to the window.
5.If the window object can’t handle the event, it passes the event to the singleton app object.
6.If the app object can’t handle the event, it discards the event.
The app on the right follows a slightly different path, but all event delivery paths follow these heuristics:

1.A view passes an event up its view controller’s view hierarchy until it reaches the topmost view.
2.The topmost view passes the event to its view controller.
3.The view controller passes the event to its topmost view’s superview.
Steps 1-3 repeat until the event reaches the root view controller.

4.The root view controller passes the event to the window object.
5.The window passes the event to the app object.

Important: If you implement a custom view to handle remote control events, action messages, shake-motion events with UIKit, or editing-menu messages, don’t forward the event or message to nextResponder directly to send it up the responder chain. Instead, invoke the superclass implementation of the current event handling method and let UIKit handle the traversal of the responder chain for you.

你可能感兴趣的:(对象)