Cocoa Programming/Status items

What is a status item? edit

A status item is an icon that's installed in the menu bar, near the clock and other MacOS common icons, such as Volume, Spotlight, etc. These icons provide a place to keep, for example, important shortcuts for your application, or just an icon that identify the current application status; often they are associated with menus. In this document I'll explain how to build a status item, rather than explain all the class reference which is included with your Xcode, and available on the ADC site.

Building a status item application edit

The code

First of all you have to remember that your status item it's a separate application: when you close the application, the status item is deallocated. Generally status items are used to control and monitor a process that the end user doesn't see, or are theirself a controller of something (see "QuickTunes").

We create a new class called "myStatusItem". The status item class is NSStatusItem, you have to instantiate it in your header, together with all you need:

#import <Cocoa/Cocoa.h>

@interface myStatusItem : NSObject {

IBOutlet NSMenu *myMenu;

NSStatusItem *statusItem;

NSImage *statusImage;
NSImage *statusAltImage;

}
@end

How can you see we have introduced two images which are the main and the alternate icons for our status item, these images are 18x18.

The next step is that of writing the true program, the ".m" file: we have to tell MacOS that we want to install a status item. This is made by this line of code

statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength: NSSquareStatusItemLength] retain];

Next we can allocate the two images with

NSBundle *bundle = [NSBundle mainBundle];
statusImage = [[NSImage alloc] initWithContentsOfFile: [bundle pathForResource: @"statusIcon" ofType: @"png"]];
statusAltImage = [[NSImage alloc] initWithContentsOfFile: [bundle pathForResource: @"statusAltIcon" ofType: @"png"]];

Then the last lines, customize our status item:

[statusItem setImage: statusImage];
[statusItem setAlternateImage: statusAltImage];
[statusItem setMenu: myMenu];
[statusItem setToolTip: @"A tooltip"];
[statusItem setHighlightMode: YES];

It'd be nice to write also another method, the dealloc method, after the - (void) awakeFromNib, which is the main method called after the application has started. With the dealloc we help the memory management by release some things that we don't need, in fact when this happens, our app has already terminated. With this code we want to release the images that make the icon:

- (void) dealloc {
[statusImage release];
[statusAltImage release];
[super dealloc];
}


The interface

When we created our application, using the "cocoa application" template, Xcode made also a NIB file, that consist in our program's UI and resources. Double click the NIB for adding the interface. Since we've already written our code and specified some outlets and our classes, we can refresh the NIB standard contents by moving in the Classes view (in the main window of Interface builder) and select "Read files..." from the classes menu; we select our ".h". The myStatusItem class will be selected, right click it and Instantiate. Next drop in the instance view a NSMenu item and name it like you did in the code, in this case "myMenu". You can add NSMenuItem (s) under your menu and add actions to them.


Connecting code and interface

Cocoa uses the outlets to connect code and interface. If you remember we defined an outlet, NSMenu: let's connect it! go to the Instances view and select the "blue box", your app's instance. Open the Inspector and go to the Connections panel. As you can see there's listed "myMenu". Control-drag from the app instance to the NSMenu icon "myMenu" and then hit the "Connect" button. That's all. Now if you press the build and go button you'll see a NSStatusItem in your status bar. (You have to add the two images to your active target in your project).