NSStatusItem appears briefly on launch, but promptly disappears

3.3k views Asked by At

I'm starting to get back into Cocoa development after not working on anything for a few months. Originally when I started I was using Snow Leopard and Xcode 3. I'm now running Lion with Xcode 4.2 and I'm running into some issues that I hadn't run into before.

I believe it's probably the fact that I've never used ARC before, so I'm sure I'm missing something.

I'm trying to create Statusbar application, without a main window, or dock icon. When I run the application the Statusbar icon for my application appears briefly, for about a second, but then disappears.

Heres my code.

QuickPlusAppDelegate.h

#import <Cocoa/Cocoa.h>

@interface QuickPlusAppDelegate : NSObject <NSApplicationDelegate>

@property (assign) IBOutlet NSWindow *window;
@property (assign) NSStatusItem *statusItem;
@property (weak) IBOutlet NSMenu *statusItemMenu;

@property (strong) NSImage *statusItemIcon;
@property (strong) NSImage *statusItemIconHighlighted;
@property (strong) NSImage *statusItemIconNewNotification;

@end

QuickPlusAppDelegate.m

#import "QuickPlusAppDelegate.h"

@implementation QuickPlusAppDelegate
@synthesize statusItemMenu = _statusItemMenu;

@synthesize window = _window, statusItem = _statusItem;
@synthesize statusItemIcon = _statusItemIcon, 
    statusItemIconHighlighted = _statusItemIconHighlighted, 
    statusItemIconNewNotification = _statusItemIconNewNotification;

- (void) awakeFromNib
{
    NSBundle *appBundle = [NSBundle mainBundle];
    _statusItemIcon = [[NSImage alloc] initWithContentsOfFile:[appBundle pathForResource:@"statusItemIcon" ofType:@"png"]];
    _statusItemIconHighlighted = [[NSImage alloc] initWithContentsOfFile:[appBundle pathForResource:@"statusItemIconHighlighted" ofType:@"png"]];
    _statusItemIconNewNotification = [[NSImage alloc] initWithContentsOfFile:[appBundle pathForResource:@"statusItemIconNewNotification" ofType:@"png"]];

    _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
    [_statusItem setImage:_statusItemIcon];
    [_statusItem setAlternateImage:_statusItemIconHighlighted];
    [_statusItem setHighlightMode:YES];
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // empty
}

@end

Edit If you see anything wrong with my code please let me know. I definitely would some critique so I can get better.

Another Edit It seems as if the Statusbar icon disappears when the main window itself loads.

2

There are 2 answers

3
ipmcc On BEST ANSWER

_statusItem will be autoreleased in this case.

    _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];

This returns an autoreleased object. _statusItem is just an iVar. Not only that, but you declare the property as assign:

@property (assign) NSStatusItem *statusItem;

What you probably want to do here is make the property strong and then, instead of setting the ivar directly, use the property to set it. So like this:

@property (strong) NSStatusItem *statusItem;

and then:

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

That will cause the statusItem be retained. I'm betting that what's happening now is that it gets released when the autorelease pool pops, and then your app crashes the next time anything tries to access it, thus causing it to disappear from the menu bar. Running it through the Zombies instrument would tell you for sure if that was what was happening. But in general, your app needs to have a strong reference to that object for it to stick around.

0
2Yootz On

I was having this issue in Xamarin. For awhile it worked fine. Then I added extra code to the FinishedLaunching method and the StatusItem started vanishing. I had this code generating the StatusItem:

    public override void AwakeFromNib ()
    {
        var statusItem = NSStatusBar.SystemStatusBar.CreateStatusItem (30);
        statusItem.Menu = mainMenu;
        statusItem.Image = NSImage.ImageNamed ("menuicon");
        statusItem.AlternateImage = NSImage.ImageNamed ("menuicon_selected");
        statusItem.HighlightMode = true;
    }

Eventually, I found my problem. In my Xcode I had declared this property in my AppDelegate but I wasn't using it:

@property(nonatomic, retain) IBOutlet NSStatusItem *statusItem;

When I removed the var the StatusItem continued to show in its infinite glory :)

    public override void AwakeFromNib ()
    {
        statusItem = NSStatusBar.SystemStatusBar.CreateStatusItem (30);
        statusItem.Menu = mainMenu;
        statusItem.Image = NSImage.ImageNamed ("menuicon");
        statusItem.AlternateImage = NSImage.ImageNamed ("menuicon_selected");
        statusItem.HighlightMode = true;
    }

I didn't have to change it to (strong). In fact I tried but it didn't persist when copying back to Xamarin Studio.