我对可可很新,并且真的与第一响应者的整个概念相混淆。对象何时成为第一响应者? 假设我的视图层次结构中的每个对象都接受第一个响应者状态,如果没有明确的“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”事件?
这对我来说真的很困惑。如果有人可以告诉我上面发生了什么,我会非常感激,第一响应者最初是如何设置的?
谢谢!
答案 0 :(得分:1)
鼠标事件的事件链与其他事件不同 - 它们总是被发送到光标下最顶层的NSView,而不是第一个响应者。这很好 - 如果您实际点击了窗口中其他位置的按钮,您不希望将mouseDown:
事件发送到您正在编辑的文本字段(这将是firstResponder
)
如果您希望始终获取鼠标移动事件,请在视图中添加NSTrackingArea
,如下所示:
entireViewTrackingArea = NSTrackingArea(rect: .zero, options: [.mouseMoved, .activeInActiveApp, .inVisibleRect], owner: self, userInfo: nil)
addTrackingArea(entireViewTrackingArea!)
我不推荐setAcceptsMouseMovedEvents:
因为它对你想要的东西有点极端。 (您通常不希望窗口中的每个视图都获得鼠标移动事件,这可能很昂贵。)