神秘的第一响应者变化

Posted

技术标签:

【中文标题】神秘的第一响应者变化【英文标题】:Mysterious First Responder change 【发布时间】:2014-07-23 06:17:42 【问题描述】:

我目前正在开发首选项窗格。我希望自定义 NSView 子类在启动我的首选项窗格时具有 First Responder 状态。我将我的视图设置为第一响应者(在我的 NSPreferencePane 子类中):

- (void)didSelect 
    NSLog(@"Before: %@", self.mainView.window.firstResponder);

    [self.keyboardView.window makeFirstResponder:self.keyboardView];

    NSLog(@"After: %@", self.mainView.window.firstResponder);

此后我定期检查当前的 First Responder,似乎在 didSelect 完成后不久,First Responder 更改为我的 NSPreferencePane 的 mainView。我的程序中没有任何东西导致这种变化。这是输出:

Before: <NSTextView: 0x60000013dce0>
//presumably the System Preferences search field.
After: <AMKeyboardView: 0x608000321a40>
//successfully set to the desired AMKeyboardView.
<NSView: 0x61000013ea00>
//<--- magic change to mainView, for seemingly no reason.

在 Interface Builder 中,我的窗口有一个名为 initialFirstResponder 的插座。我不能将此插座设置为任何东西,因为我的视图是以编程方式添加的,并且不能由 Interface Builder 访问。我怀疑缺少连接会导致将第一响应者设置为 mainView 的默认行为。

我可以做些什么来解决这个问题?

【问题讨论】:

您究竟为什么希望UIView 成为第一响应者? 这是一个接受键盘输入的NSView 子类。 (实现 keyDown) 哦,OSX 领域,帮不了你。 你能在你的主视图中实现becomeFirstResponder并设置一个断点来看看它被调用的原因吗? 这是来自那个神秘调用cl.ly/image/450f220n3a3W的堆栈跟踪 【参考方案1】:

查看Secrets Preference Pane的源代码后,我发现了他们在打开首选项窗格时将自己的搜索框设置为第一响应者的方法。我通过添加到我的didSelect 方法将此方法应用于我自己的偏好窗格:

[self.mainView.window performSelector:@selector(makeFirstResponder:)
                           withObject:self.keyboardView
                           afterDelay:0.0];

...它的工作原理!但是,我不知道 为什么 它有效。我假设 0.0 延迟实际上并不是真正的即时,这使得 performSelector 在发生神秘的第一响应者更改之后运行。

我想这回答了我的问题,但又引出了一个新问题:为什么会这样?

【讨论】:

我不会对这样的事情进行如此多的调查。如果我在多年的 Mac 编程中学到了一件事,那就是 Apple 所做的事情总是不可预测的。 @IvanKramarchuk 哈哈,很高兴这能帮上忙,这么多年了。我只是建议您将0.0 增加到喜欢0.01 或其他内容,因为0.0 可能会导致行为不太可靠

以上是关于神秘的第一响应者变化的主要内容,如果未能解决你的问题,请参考以下文章

访问 MFMessageComposeViewController 的第一响应者

辞去 Push Segue 的第一响应者

如何将动作从 NSToolbar 项发送到 TabViews 的第一响应者

UITextField 没有成为集合视图中的第一响应者

Swift 如何让所有 uiTextfield 上的第一响应者辞职

关闭具有多个文本字段的第一响应者/键盘