This tutorial assumes you have a basic knowledge of Objective-C. In this tutorial, we will walk-through on how to create a status bar only application for the Mac OS X. The final project can be downloaded from here.
What is a Menu Bar Extra?
They are extra menus that are visible at the right side of the menu bar. Some of the in-built menu extras are the battery indicator, time indicator. Menu bar extras are typically used to display application/system status information. Two things to note about the Menu bar extras are that
- If there are too many menu bar extras, the OS will remove some of them to avoid crowding and to provide space for application menus.
- The menu can also be disabled by the user.
Some websites call this kind of application a menulet application or a status bar application.
Implementation
To start off, we create a new Project in Xcode.
Open Xcode. File->New Project. Choose the “Cocoa Application” and click “Choose”. Next, Xcode should ask you to give a name for the project. Pick a name and directory for the project. In this example, the project name will be “StatusMenuApp”. Once you have chosen a project name and location, click “Save”.
Xcode should have created a new project with some default files. The two folders “Classes” and “Resources” are the most important folders for this walk-through. You can ignore the remaining folders for this example.
First, we will add an NSMenu outlet in the In the StatusMenuAppAppDelegate.h to which the menus can be referenced to. Also we will add a NSStatusItem that will eventually become the status bar menu item.
@interface StatusMenuAppAppDelegate : NSObject {
NSWindow *window;
IBOutlet NSMenu *statusMenu;
NSStatusItem * statusItem;
}
@property (assign) IBOutlet NSWindow *window;
@end
We will now create the MenuItems that will be available in the application. To do this, we open the MainMenu.xib in the Interface Builder. For this example, we will not touch the existing Menu in nib. Drag and drop another “Menu” object from the Library into the Document window. Give each of the MenuItem a unique title. Now we have to link the Menu object to the statusMenu outlet. To do this, CTRL+click on the StatusMenuAppDelegate object and drag and release the pointer on the Menu object. This should open up a panel titled “Outlets”. This panel will show all the Outlets available in the StatusMenuAppDelegate class. In our example, there is only one outlet. Click on the ’statusMenu’ to link the Menu object to statusMenu. Finally, delete the Window object. Save the nib file and close Interface Builder.
Now we move on to actually creating the Status Bar Menu. In the “StatusMenuAppDelegate.m”, we override the function awakeFromNib. A awakeFromNibmessage is sent to every object that is loaded from a Nib(.nib or .xib) file. Firstly, we will create the NSStatusItem. To do so, we have to call
- (NSStatusItem *)statusItemWithLength:(CGFloat)length
The parameter length can take the following two values:
- NSVariableStatusItemLength -Makes the status item length dynamic, adjusting to the width of its contents.
- NSSquareStatusItemLength – Sets the status item length to the status bar thickness.
For this example, we will use the NSVariableStatusItemLength.
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
Secondly, we have to add the statusMenu to the statusItem. To do so, we all the following code:
[statusItem setMenu:statusMenu];
Thirdly, we give a title for the statusItem. This will be seen in the Menu Extras.
[statusItem setTitle:@"Status"];
If you would like to see an image instead of text, you can use the following methods:
- (void)setImage:(NSImage *)image
-(void)setAlternateImage:(NSImage *)image
Lastly, we want to highlight the menu when the user clicks on it. So we use the following code.
[statusItem setHighlightMode:YES];
By default, the highlight mode will be set to NO.
The StatusMenuAppDelegate.m file should look like this now.
#import "StatusMenuAppDelegate.h"
@implementation StatusMenuAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
}
-(void)awakeFromNib{
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
[statusItem setMenu:statusMenu];
[statusItem setTitle:@"Status"];
[statusItem setHighlightMode:YES];
}
@end
Since we want the app to only appear on the status menu, the last step is the most important one.We need to modify the StatusMenu-Info.plist file. Double click to open this file. Add a new property with key “Application is agent (UIElement)” and value as TRUE(i.e. check the box). Your .plist should look like this.
Final output of the program should look like this:




#1 by Alec on March 4, 2010 - 4:11 pm
Quote
“To do this, CTRL+click on the StatusMenuAppDelegate object and drag and release the pointer on the Menu object. ”
StatusMenuAppDelegate doesn’t show up in my MainMenu.xib (English) window like in your screenshot. What did I do wrong?
Or better, could you explain more about creating the NSMenu outlet in StatusMenuAppAppDelegate.h?
Thanks
#2 by Alec on March 4, 2010 - 4:13 pm
Quote
I’m running XCode Version 3.1.3 on Mac OS X 10.5, by the way
#3 by aravind88 on March 5, 2010 - 7:41 pm
Quote
Hi Alec,
Thanks for bringing this up. I should have mentioned the above steps were for Xcode Version 3.2 and Mac OS X 10.6. You can still achieve the same things in a 10.5 as well.
These are the steps you could follow. I am assuming you already have a new project.
1) Create a new Objective-C class that extends NSObject, say for this example, we name it MenuSetter.
2) In the header file, add two variables
IBOutlet NSMenu *statusMenu;
NSStatusItem * statusItem;
3) In the implementation file(.c) file, add the following code.
-(void)awakeFromNib{
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
[statusItem setMenu:statusMenu];
[statusItem setTitle:@"Status"];
[statusItem setHighlightMode:YES];
}
4) Open the MainMenu.xib file. Drag and Drop a “Object” from the Library(shift+cmd+L) into the list. Open the Inspector(shift+cmd+I) and then the Identity Tab.
5) In the Identity Tab, select the class as MenuSetter.
6) Now, you should be able to CTRL+Click on the MenuSetter object and drag and release the pointer on the Menu object.
Try this out.
Creating the NSMenu outlet.
We will be using the NSMenu outlet as the menu that will appear when the user click on the statusbar item. I decided to use the Interface builder to create the menu. You could also programatically do it.
“To do this, CTRL+click on the StatusMenuAppDelegate object and drag and release the pointer on the Menu object. ”. This action will map the NSMenu object in the Interface builder to the variable in the StatusMenuAppDelegate file. So, if you want to modify/use the menu, you would then just refer to the variable. That is what we are doing when we say [statusItem setMenu:statusMenu]; The statusMenu is automatically mapped to menu in the Interface Builder.
Let me know if the answers your question.
#4 by Michael on April 10, 2010 - 7:52 pm
Quote
Hey, im running 10.6, Xcode 3.2.1 and just can’t seem to get this working
can you give me a link to the xcode project so i can have a look?
Thanks
#5 by aravind88 on April 17, 2010 - 9:58 am
Quote
Hi Micheal,
I have uploaded the project here. Let me know if you still have trouble.
Good Luck,
Aravind
#6 by Nava on April 29, 2010 - 3:03 pm
Quote
Hi,
Thank you for a great example. How can I add a search bar to a menu like it’s done in spotlight?
Thanks in advance
#7 by Luca on May 22, 2010 - 5:14 pm
Quote
Hey, How can I put an image file in this code?
-(void)setImage:(NSImage *)image
-(void)setAlternateImage:(NSImage *)image
How about this?
-(void)setImage:(NSImage *)icon.png
-(void)setAlternateImage:(NSImage *)icon.png
Thanks!
#8 by aravind88 on May 22, 2010 - 8:17 pm
Quote
Hi Luca,
To get a NSImage, you would have to say
NSImage * image = [NSImage imageNamed:@"imageName"];
assuming your image file name is imageName.png.
Hope this helps,
Aravind
#9 by paul rostorp on May 25, 2010 - 12:18 pm
Quote
Hello, I just discovered this site and this very good tutorial. I am beginning with mac os x programming and was wondering if it was possible to display, instead of an NSMenu, a usual NSWindow ( small window ) .
Thank you,
#10 by Joshua on May 31, 2010 - 2:57 pm
Quote
Hey i got the menu app working perfect and i modifed some menu items to open a window using “orderFront:” action, that opens the window fine and i can see it and everything, but for some strange reason after you close that window, the program dies, this happening in the debugger.
-ouput-
Program received signal: “EXC_BAD_ACCESS”.
kill
quit
Its something wrong with memory management, because when i uncheck “release when closed” on the inspector for that window it doesnt crash, but i dont want that window to save things people do i want it to close and forgot the stuff.
#11 by Wind Up Toy on June 19, 2010 - 2:49 pm
Quote
Great tutorial! Any way to do this using AppleScriptObjC?
Thanks!
#12 by Wind Up Toy on June 19, 2010 - 4:18 pm
Quote
When using
NSImage * image = [NSImage imageNamed:@"imageName"];
I get a warning that NSImage may not respond to -imageNamed.
Where should the png file be located in the project folder?
Thanks!
#13 by Dirk on June 22, 2010 - 11:47 pm
Quote
Great Article Thank you. I am trying to make a small window pop up when the user clicks on the menu item but I am not sure how to proceed? I have designed the form, just not sure how to best hook it up.
Any suggestions?
#14 by Sam on June 23, 2010 - 9:53 am
Quote
I am in the same boat. I followed the above which makes sense but I am stuck attaching events and making these menuItems work? OnliNe tutorials appear to be for the older Xcode — please point me to the right direction. Thanks in advance
#15 by Lina on June 24, 2010 - 9:20 am
Quote
I have the same issue. I am new to cocoa coming from a C++ MFC Windows Development background. I like what I see though old habbits are not helping.
Could you please add/post a short sample showing how we can attach events/actions to these menuItems?
I googled for a couple of days and the instructions I found are for older Mac OSXX/Xcode just like Sam says.
Please,please help us
#16 by Sam on June 28, 2010 - 10:19 am
Quote
=(
#17 by Alex on June 28, 2010 - 9:30 pm
Quote
How can we make the Menu1, Menu2, Menu3 active and birng up a window?
#18 by Alex on June 28, 2010 - 9:55 pm
Quote
I learned how we can attach/link interface objects, I just dont know how to enable these Menu items…
#19 by Jason Soo on July 3, 2010 - 2:40 am
Quote
Great help! Thanks!
Short sweet and to the point of the article title. Love it.
#20 by hiren on August 16, 2010 - 7:20 am
Quote
In my Application i want to hide the application symbol from the status bar, All thiggs going currectly but i could no able to get address of status item when i try to hide the StatusItem.
When i have put breakPoint and try to see his value it shows 0*0
If i add the symbol of application the it show two symbol of that app and allows to remove second symbol.but not one.
so can any oue help what is problem
#21 by Al Lewis on February 19, 2011 - 11:27 pm
Quote
Is there a way for the MainMenu.xib window to open besides double clicking the MainMenu.xib file? I’ve read other tutorials, but they have told me to double click this file, and a new window should open, and yet nothing happens when I do so. Please help!!!
#22 by Björn on February 26, 2011 - 5:54 am
Quote
Thanks for this tutorial