1

My project is document-based, and the code to load a status menu is only executed if I put it under awakeFromNib.

#import "StatusMenuAppDelegate.h"

@implementation StatusMenuAppDelegate

@synthesize window = _window;

-(void)awakeFromNib {
    myStatusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
statusImage = [NSImage imageNamed:@"statusNorm.png"];
[myStatusItem setImage:statusImage];
[myStatusItem setHighlightMode:YES];
[myStatusItem setMenu:myStatusMenu];
}
@end

But, in my test project (non-document-based), the code is executed fine in applicationDidFinishLaunching. Why? Wouldn't I want to ideally use this function for my status menu?

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
janeh
  • 3,734
  • 7
  • 26
  • 43

1 Answers1

1

The applicationDidFinishLaunching: message is sent by the application object to its delegate. It is not sent to any other objects.

You can certainly respond to that message in your document objects, but they will never receive it because nothing sends it to them. That's why anything you do in that method in a document object, or any other object that isn't the application's delegate, doesn't happen.

awakeFromNib is one place you could create the status item. I would probably do it in windowControllerDidLoadNib:.

That's assuming you really want to have one status item per document, which probably doesn't make sense. If that's not what you want, you should move creation, ownership, and management of your status item to a singleton object, which should be created—probably within applicationDidFinishLaunching:—by the application's delegate, and have any and all documents interact with that object as needed.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • Thanks. I created an object (KBAppDelegate.h) and made it application delegate, and now it works with applicationDidFinishLaunching. (I want the status bar to stay on no matter what docs are open, and load asap, that's why I think applicationDidFinishLaunching would be the best for that). Why would I need my KBAppDelegate to be a singleton, rather than a regular class? – janeh Dec 16 '11 at 14:13
  • @janeh: I would make a separate object to create and own the status item. KBAppDelegate should be the application's delegate and as little as possible else. It should create the status item owner object in `applicationDidFinishLaunching:`; that object should then in turn create and own the status item, and be a singleton so that other objects can get to it easily and to prevent there from ever being more than one of it. – Peter Hosey Dec 16 '11 at 17:59
  • Ok. In my KBAppDelegate.h I also have dealloc code they releases status bar images. If I move status creation to another object, call the method from applicationDidFinishLaunching, my dealloc won't know what images I am trying to release, right? So, I'd have to create some cleanUpMethod in KBStatusMenu.m, and call it from KBAppDelegate.m. I guess my question is can dealloc be called from any object or just application delegate? (I tried testing it with NSLog, but I guess that won't work.) – janeh Dec 17 '11 at 18:51
  • @janeh: The object that creates the status item should also create/load the images for the status item. It would then, consequently, be obliged to release those in its `dealloc`. `dealloc` is called as a consequence of the last release of an object; never, *ever* call it directly. It should be called when your app delegate releases the status-item-owner object that it previously created. – Peter Hosey Dec 17 '11 at 19:28
  • Thanks! My head hurts now: I have another issue where only the icon for the status menu shows up. I started another thread. :-/ – janeh Dec 19 '11 at 04:36
  • @janeh: Reading your code in that question (http://stackoverflow.com/q/8557129/30461), I notice that you have -buildStatusItem returning the NSStatusItem, and the application's delegate holding onto it. There is no reason why any other object should have access to the NSStatusItem; it should be private property of KBStatusMenu, which should have public properties for any and all things that your status item indicates or has in its menu. For example, a `target` for all the menu's actions to be sent to, and one or more properties that influence which icon image KBStatusMenu uses. – Peter Hosey Dec 19 '11 at 05:47
  • I am still working on it :-/ I am stupid, sorry, but… in 'applicationDidFinishLaunching', if I create an instance of KBStatusMenu (a singleton), and if I shouldn't return NSStatusItem to that instance, what is the use for that instance? What should it hold? – janeh Dec 22 '11 at 03:59
  • “if I create an instance of KBStatusMenu…, and if I shouldn't return NSStatusItem to that instance…” That doesn't make sense. The KBStatusMenu instance creates the NSStatusItem instance, as it should, and it should own the NSStatusItem instance, and both of these things should be private—it should not make the NSStatusItem instance available to other objects. The app delegate creates the KBStatusMenu instance; other objects should have to talk to the KBStatusMenu if anything changes that should be reflected in the status item. – Peter Hosey Dec 22 '11 at 04:22
  • Thanks, I pretty much got it, i just have to rewrite a regular init code to be a singleton! – janeh Dec 22 '11 at 15:12