响应者链

响应者链是应用事件或动作消息的响应者对象的链接序列,当给定的响应者对象不处理特定的消息时,对象将消息传递给链中的它的继任者(即下一个响应者)。这允许响应者对象将处理消息的责任委托给其他的,通常是更高级别的对象。应用程序工具包自动构造响应者链,如下所述,但是您可以使用NSResponder中的setNextResponder:方法将自定义对象插入以作为其中的部分,并且可以使用nextResponder检查它(或遍历它)。

一个应用程序可以包含任意数量的响应者链,但是在任意时间内只有一个是激活的。响应者链对于事件消息和操作消息是不同的,如下文所述。

事件消息的响应者链

几乎所有的事件消息都使用单个窗口的响应者链——即发生关联用户事件的窗口。事件消息的默认响应链以NSWindow对象首先向其传递消息的视图开始。焦点事件消息的默认响应链以窗口中的第一个响应开始;鼠标或触摸板事件的默认响应链从用户事件发生的视图开始。在上述位置中事件如果不被处理,则会继续向上层的视图层次结构传递直到窗口本身的NSWindow对象。第一个响应者通常是窗口中的“选中”视图对象,它的下一个响应者是它的包含视图(也称为它的父视图),以此类推直到NSWindow对象。如果一个NSWindowController对象正在管理窗口,它将成为最终的一个响应者。你可以在NSView对象之间插入其他响应者,甚至在靠近链顶端的NSWindow对象上面,这些插入的响应者可以接收事件和操作消息。如果没有找到处理事件的对象,在响应链中的最后一个响应者将会调用noResponderFor:方法,对于键控事件,它只会发出哔哔声。事件处理对象(NSWindow或者NSView的子类)可以重写该方法去执行必要的其他动作。

动作消息的响应者链

对于动作消息,应用程序工具包构造了一个更复杂的响应链,它根据两个因素变化:

  • 该程序是否基于文档架构类型,如果不是,它的window是否由NSWindowController管理。
  • 应用程序当前是否显示一个焦点窗口和一个主窗口

动作消息的响应者链相比事件消息更复杂,因为为了检测他们的对象,动作消息需要有一个更灵活的运行时机制,它们不像事件消息那样局限于单个窗口。

最简单的例子是一个激活的非文档类型的窗口没有相关的面板或二级窗口显示,即,一个主窗口也是焦点窗口,在这种情况下,响应链如下:

  1. 主窗口的第一个响应者和在视图层次结构上的后续响应者对象
  2. 主窗口自身
  3. 主窗口代理(不需要继承自NSResponder
  4. 应用程序对象,NSApp
  5. 应用程序对象的代理(不需要继承自NSResponder

上述响应链的图片展示如图所示:

图1 操作消息的非基于文档的应用程序的Responder chain
这里写图片描述
如上图所示,NSWindow对象和NSApplication对象给他们的委托一个机会来处理动作消息,就像他们是响应者一样,即使一个委托不是正式在响应者链中(也就是说,一个窗口或应用程序对象的nextResponder消息不返回代理)。

当应用程序同时显示主窗口和焦点窗口时,两个窗口的响应者链都可以包含在动作消息中。正如在窗口分层和窗口类型中解释的那样,主窗口是最前面的文档或应用程序的窗口,主窗口通常也有焦点状态,这意味着它们是当前用户输入的焦点。但是主窗口可以有一个与之关联的辅助窗口或面板,例如Find面板或显示文档窗口中选择的详细信息的Info窗口,当这个辅助窗口是用户输入的焦点时,它就是焦点窗口。

当应用程序有一个主窗口和一个单独的焦点窗口显示时,焦点窗口的响应者链将首先对动作消息进行处理,然后是主窗口的响应者链,完整的响应链由这些响应者和代理组成:

  1. 焦点窗口的第一个响应者和在视图层次结构上的后续响应者对象
  2. 焦点对象自己
  3. 焦点对象的代理(无需继承自NSResponder
  4. 主窗口的第一个响应者和在视图层次结构上的后续响应者对象
  5. 主窗口自己
  6. 主窗口的代理(无需继承自NSResponder
  7. 应用程序对象,NSApp
  8. 应用程序对象代理(无需继承自NSResponder

如上所述,焦点窗口和主窗口的响应者链中的全局应用程序对象相同,并且响应者链的代理是主窗口响应者链末端的响应者。这种设计适用于其他类型应用程序的响应链:基于文档体系结构的响应链和使用NSWindowController对象进行窗口管理的响应链,在后者下,默认的主窗口响应者链由以下响应者和代理组成:

  1. 主窗口的第一个响应者和在视图层次结构上的后续响应者对象
  2. 主窗口自身
  3. 窗口的NSWindowController对象(继承自NSResponder
  4. 主窗口代理
  5. 应用程序对象,NSApp
  6. 应用程序对象的代理

下图显示使用NSWindowController对象的非基于文档的应用程序的响应链。

图2 带有NSWindowController对象(操作消息)的非文档应用程序的Responder chain
这里写图片描述

对于基于文档的应用程序,主窗口的默认响应者链由以下响应者和代理组成:

  1. 主窗口的第一个响应者和后续在视图层次结构上的响应者对象
  2. 主窗口自身
  3. 窗口的NSWindowController对象(继承自NSResponder
  4. 主窗口代理
  5. NSDocument对象(如果与主窗口代理不同)
  6. 应用程序对象,NSApp
  7. 应用程序对象的代理
  8. 应用程序的文档控制器(是一个NSDocumentController对象,未继承NSResponder

图3 展示基于文档应用程序的响应者链

图3 操作消息的基于文档的应用程序的Responder chain
这里写图片描述

总之,相应链总体按如下路径传递:

非文档类型:

First responder -> View hierarchy -> NSWindow -> NSWindowController -> NSWindow delegate -> NSApp -> App delegate

文档类型:

First responder -> View hierarchy -> NSWindow -> NSWindowController -> NSWindow delegate -> NSDocument -> NSApp -> App delegate -> NSDocumentController

猜你喜欢

转载自blog.csdn.net/zzl819954692/article/details/81910752