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.
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.
_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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With