1

I have a statusitem in the system menu bar that makes a popover appear when it is clicked. I would like to make the popover automatically appear when the application is first launched. I tried to add the [self clickStatusBar:self] to the awakeFromNib method but it doesn't work. Anyone know how to accomplish this?

Here are my current methods:

- (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];
}

I tried adding applicationDidFinishLaunching: as

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

but I get an error of -[AppDelegate bounds]: unrecognized selector sent to instance

cacau
  • 3,606
  • 3
  • 21
  • 42
wigging
  • 8,492
  • 12
  • 75
  • 117

1 Answers1

3

In awakeFromNib: the application is not fully launched yet, only this NIB file has been unmarshalled. At this point this method gives you a hook to complete (object-local) initialization. The application is (quite likely) not ready to process events or perform actions.

You should trigger that action from applicationDidFinishLaunching: method, an optional method in the application delegate, and pass in the status item like a click would do (because you query it for bounds).

Update. This is trickier than I had thought. Turns out, the NSStatusItem doesn't have a view associated at that point when the delegate gets called. I'd venture to say that is a bug with NSStatusItem. When statusItem.view is called in applicationDidFinishLaunching:, the popover method receives nil and complains.

The only (partial, see below) workaround that I have found is to set a button as view manually in awakeFromNib: like so:

- (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;
}

That way you'd have a view around when the application is done launching. But beware, it doesn't look like the default one.

PS. And curiously, and does not even work every time. I have to drop the ball here. Sorry. Maybe save the location in the defaults when somone clicks. I think I saw such an inconsistency in Cloud.app and with a popover next to a status item, and maybe now we know why :)

febeling
  • 1,390
  • 1
  • 12
  • 29
  • Well I tried that but I'm still getting an error (see my updated question). I think I'm calling the `clickStatusBar` incorrectly. – wigging Feb 29 '12 at 18:30
  • You can't call that action on the app delegate. You need to put an outlet into the app delegate, put a connection into place in IB from that status item to the outlet, and then call action in the item via that outlet variable or property. – febeling Feb 29 '12 at 18:36
  • Sorry, I got confused. Disregard the IBOutlet part (I'll edit the aswer accordingly). You expect the status item as the sender to the action, so when you call it programmatically, you need to pass that in, in place where now is `self`. (I assume that the above code is a controller or the app delegate, and the popover works with clicking already.) – febeling Feb 29 '12 at 19:21
  • `[self clickStatusBar:statusItem]` does not work either. Could you provide an example? And yes, the popover works when you click the status bar title. – wigging Feb 29 '12 at 19:33
  • I have made a gist of it, if anyone wants to review: https://gist.github.com/1944898 – febeling Feb 29 '12 at 22:21
  • Wow, I didn't think it would be that involved. Thanks for the effort though. – wigging Mar 01 '12 at 03:56