LSUIElement 的行为与 activateIgnoringOtherApps 不一致

Posted

技术标签:

【中文标题】LSUIElement 的行为与 activateIgnoringOtherApps 不一致【英文标题】:LSUIElement behaves inconsistently with activateIgnoringOtherApps 【发布时间】:2010-12-23 21:03:03 【问题描述】:

具体来说,它在文本字段焦点方面的行为不一致。

我有一个 LSUIElement 弹出状态菜单。在该菜单中有一个包含文本字段的视图。文本字段必须是可选择的——不一定是默认选择,但可以选择。

当状态项被点击时触发

[NSApp activateIgnoringOtherApps:YES];

它工作,大约一半的时间。* 状态菜单的另一半似乎认为自己“在后台”,即使单击它也不会让我将注意力集中在文本字段上。 (我知道状态项点击触发器正在触发 b/c 上面有一个 NSLog。)

这是 Apple 处理这些状态项的方式中的错误,还是我错误地处理了 activateIgnoringOtherApps?

*事实上,它似乎只是在另一个应用程序激活后第一次失败。之后就可以正常使用了。

完整的sn-p:

-(void)statusItemClicked:(id)sender 
    //show the popup menu associated with the status item.
    [statusItem popUpStatusItemMenu:statusMenu];

    //activate *after* showing the popup menu to obtain focus for the text field.
    [NSApp activateIgnoringOtherApps:YES];


【问题讨论】:

【参考方案1】:

终于想出了一个解决方法。

不要在您的点击处理程序中弹出菜单,而是激活应用程序,然后安排一个 NSTimer 无延迟地弹出菜单:

-(void)pop:(NSTimer *)timer 
    [statusItem popUpStatusItemMenu:theMenu];


-(void)statusItemClicked:sender 
    [NSApp activateIgnoringOtherApps:YES];
    [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(pop:) userInfo:nil repeats:NO];

pop: 在下一帧被调用,因此延迟是难以察觉的,但足够长的时间让activateIgnoringOtherApps: 在同一帧中弹出菜单时执行任何阻止其按预期工作的事情。

【讨论】:

【参考方案2】:

根据经验,我知道您必须在弹出包含文本字段的菜单后致电activateIgnoringOtherApps:。所以你需要按这个顺序做:

- (void)statusItemClicked:sender 
    [statusItem popUpStatusItemMenu:theMenu];
    [NSApp activateIgnoringOtherApps:YES]; // FYI, NSApp is shorthand for [NSApplication sharedApplication]

根据您所说,听起来您的应用程序激活太晚了,因此在您第一次单击该项目时它没有被激活,但在后续单击时它已经被激活。

【讨论】:

肯定激活太晚了,但代码已经按照您的建议进行了结构化。在状态菜单被解除之前,似乎激活方法没有被调用(NSLog 测试似乎证实了这一点)。我不明白为什么会这样。 那么activateIgnoringOtherApps: 会在popUpStatusItemMenu: 之后立即被调用,还是该方法在菜单关闭之前不会返回?您可以尝试设置断点并通过调试器运行以查看会发生什么。 是的,使用断点它肯定会在菜单被关闭后才被调用。将我的代码添加到第一篇文章中,尽管它看起来几乎完全符合您的建议。 如果你把这两行颠倒过来会起作用吗?如果在弹出菜单之前激活应用程序?显然,仅在关闭菜单后才激活应用程序对您没有任何好处,而且我想不出菜单出现时会调用另一个挂钩。 反转它们仍然会使文本文件无法选择,并且在关闭菜单后会引发一些错误。 statusItemClicked 在 awakeFromNib 中被设置为 statusMenu 的选择器——这可能是延迟的一部分吗?

以上是关于LSUIElement 的行为与 activateIgnoringOtherApps 不一致的主要内容,如果未能解决你的问题,请参考以下文章

将 LSUIElement 转换为前台应用程序

覆盖 Android 中的 Activity/Task 行为

FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_CLEAR_TASK 行为怪异

粘性标题 - 使用标签滚动

Android Fragment 和 Activity 在方向更改时的行为

返回 Activity / Fragment 历史记录时的 Android Back Button 行为