什么是默认的第一响应者?

时间:2013-11-16 03:35:56

标签: macos cocoa

我对可可很新,并且真的与第一响应者的整个概念相混淆。对象何时成为第一响应者? 假设我的视图层次结构中的每个对象都接受第一个响应者状态,如果没有明确的“becomeFirstResponder”,那么应用程序启动后的默认第一个响应者是什么?

已更新

我应该对我的困惑更具体一点,这可能源于我为研究第一反应者行为所做的以下实验。

实验1):

此实验的目标是从第一响应者检测“mouseMoved”。根据规范,“mouseMoved”总是首先发送给第一个响应者。

我在Xcode中构建了以下层次结构:

NSWindow         - NSView                - myCustomView

myCustomView继承自NSView,实现如下:

@implementation myView

- (void)awakeFromNib
{
    [[self window] setAcceptsMouseMovedEvents:YES];
}

- (void)drawRect:(NSRect)dirtyRect
{
    [[NSColor blueColor] set];
    NSRectFill([self bounds]);
} 

- (void)mouseMoved:(NSEvent *)theEvent
{
    NSLog(@"[MYCUSTOMVIEW] mouse moved");
}
@end

当我运行上面的代码时,当我在屏幕上移动鼠标时,没有打印出任何内容。这是预期的,因为NSWindow是第一个响应者。 myCustomView从未收到过“mouseMoved”。

实验2):

我在myCustomView的实现中添加了以下内容:

- (BOOL)acceptsFirstResponder
{
    return YES;
}

当我运行代码时,仍然没有打印出任何内容。现在我很困惑,在这种情况下myCustomView不应该成为第一个响应者并接收“mouseMoved”事件吗?

有趣的是,当我在myCustomView的边界内点击鼠标时,“[MYCUSTOMVIEW]鼠标移动”消息开始显示在控制台中。我可以理解点击操作使myCustomView成为第一个响应者,但为什么不是第一个呢?

如果我再次运行代码,这一次,“[MYCUSTOMVIEW]鼠标移动”消息从一开始就显示出来。我不必再点击myCustomView了。发生了什么事?

实验3):

我更改了“acceptsFirstResponder”以返回“NO”并运行代码。 “[MYCUSTOMVIEW]鼠标移动”消息从一开始就显示出来。什么了! myCustomView不再有兴趣成为第一个响应者。为什么它仍然收到“mouseMoved”事件?

这对我来说真的很困惑。如果有人可以告诉我上面发生了什么,我会非常感激,第一响应者最初是如何设置的?

谢谢!

1 个答案:

答案 0 :(得分:1)

鼠标事件的事件链与其他事件不同 - 它们总是被发送到光标下最顶层的NSView,而不是第一个响应者。这很好 - 如果您实际点击了窗口中其他位置的按钮,您不希望将mouseDown:事件发送到您正在编辑的文本字段(这将是firstResponder

如果您希望始终获取鼠标移动事件,请在视图中添加NSTrackingArea,如下所示:

entireViewTrackingArea = NSTrackingArea(rect: .zero, options: [.mouseMoved, .activeInActiveApp, .inVisibleRect], owner: self, userInfo: nil)
addTrackingArea(entireViewTrackingArea!)

我不推荐setAcceptsMouseMovedEvents:因为它对你想要的东西有点极端。 (您通常不希望窗口中的每个视图都获得鼠标移动事件,这可能很昂贵。)