需要让 NSPopover 在 awakeFromNib 期间出现吗?

Posted

技术标签:

【中文标题】需要让 NSPopover 在 awakeFromNib 期间出现吗?【英文标题】:Need to make NSPopover appear during awakeFromNib? 【发布时间】:2012-02-29 18:02:49 【问题描述】:

我在系统菜单栏中有一个状态项,单击它时会出现一个弹出框。我想让弹出框在应用程序首次启动时自动出现。我试图将[self clickStatusBar:self] 添加到 awakeFromNib 方法中,但它不起作用。有谁知道如何做到这一点?

这是我目前的方法:

- (void)awakeFromNib 
    statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    [statusItem setTitle:@"Locating..."];
    [statusItem setTarget:self];
    [statusItem setAction:@selector(clickStatusBar:)];
    [statusItem setHighlightMode:YES];


- (void)clickStatusBar:(id)sender 
    [[self popover] showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge];

我尝试将applicationDidFinishLaunching: 添加为

- (void)applicationDidFinishLaunching:(NSNotification *)notification 
    [self clickStatusBar:self];

但我得到一个错误 -[AppDelegate bounds]: unrecognized selector sent to instance

【问题讨论】:

【参考方案1】:

awakeFromNib: 中,应用程序还没有完全启动,只有这个NIB 文件被解组。此时,此方法为您提供了一个完成(对象本地)初始化的钩子。应用程序(很可能)尚未准备好处理事件或执行操作。

您应该从applicationDidFinishLaunching: 方法触发该操作,该方法是应用程序委托中的一个可选方法,并像单击一样传递状态项(因为您查询它以获取bounds)。

更新。这比我想象的要棘手。事实证明,当委托被调用时,NSStatusItem 没有关联的视图。我敢说这是NSStatusItem 的错误。在applicationDidFinishLaunching:中调用statusItem.view时,popover方法接收到nil并报错。

我发现的唯一(部分,见下文)解决方法是在awakeFromNib: 中手动将按钮设置为视图,如下所示:

- (void)awakeFromNib

  self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];

  self.statusItemButton = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 83, 22)];
  self.statusItemButton.title = @"Locating...";
  self.statusItemButton.bordered = NO;
  [self.statusItemButton setAction:@selector(clickStatusBar:)];

  self.statusItem.view = self.statusItemButton;

这样您就可以在应用程序完成启动时查看周围的情况。但请注意,它看起来不像默认的。

PS。 奇怪的是,甚至每次都不起作用。我不得不把球丢在这里。对不起。当somone点击时,可能会将位置保存在默认值中。我想我在 Cloud.app 中看到了这种不一致,并且在状态项旁边有一个弹出框,也许现在我们知道为什么了:)

【讨论】:

嗯,我试过了,但我仍然收到错误(请参阅我更新的问题)。我想我打错了clickStatusBar 您不能在应用委托上调用该操作。您需要在应用程序委托中放置一个插座,在 IB 中建立从该状态项到插座的连接,然后通过该插座变量或属性在项目中调用操作。 对不起,我弄糊涂了。忽略 IBOutlet 部分(我将相应地编辑 aswer)。您希望状态项作为操作的发送者,因此当您以编程方式调用它时,您需要将其传入,现在是self。 (我假设上面的代码是一个控制器或应用程序委托,并且弹出框已经可以点击。) [self clickStatusBar:statusItem] 也不起作用。你能举个例子吗?是的,当您单击状态栏标题时,弹出框会起作用。 我已经做了一个要点,如果有人想评论:gist.github.com/1944898

以上是关于需要让 NSPopover 在 awakeFromNib 期间出现吗?的主要内容,如果未能解决你的问题,请参考以下文章

弹出框在状态栏中时的 NSPopover 瞬态

使用SWT Java创建NSPopover

NSPopover 和雪豹

如何以编程方式关闭 NSPopover

SwiftUI 使用键盘快捷键调用 NSPopover

NSWindow 在关闭 NSPopover 后失去了第一响应者