views:

220

answers:

1

I have an application that sits in the status bar on the Mac. It has a menu that lets you look at the app version, change some settings and quit the app.

I built it on Leopard and it works fine on Leopard. On Snow Leopard, I can see the app in the status bar and clicking on it shows the menu items. But clicking items in the menu doesn't do anything. The app isn't hung - it's doing stuff that it's expected to do. The UI thread isn't hung either - I can see the menu obviously, and and dialogs that the app causes to show on the UI thread (outside of the ones when the menu is clicked) show up fine. Compiling it on Snow Leopard targeted for 10.6 doesn't seem to change this behavior.

So I know that the app is able to create dialogs, isn't hung and is functioning. I suspect this has something to do with the menu, and handling menu clicks either in my app or in Snow Leopard.

Anyone else have suggestions on what this might be or where I should look? Any suggestions on where I can place a BP to trap whether the menu item click is actually happening?

EDIT: I've uploaded a simple repro 10.6 XCode project. I'll send a virtual beer your way if you can take a look and let me know if you see what's wrong. The app is simple - create a status bar app with 1 menu item "Quit" which calls terminate on the app. The status bar app show, the menu shows but clicking does nothing. Here's the project. It runs fine on Leopard (Clean All before you build/run) but not on Snow Leopard.

+1  A: 

It sounds likely that your menu item's action outlet isn't "hooked up" to anything in your code. I don't know from your description whether or not you created the menu in interface builder or are creating it programmatically, but the first thing to do would be to check there. Make sure that if you're creating the menu programmatically, that you've spelled the method name correctly in the @selector() (if you've got warnings that say "[class] may not respond to -Foo" that's a big tip off of a typo).

If the connections are looking good, I'd break point the method set as your action and verify that you're actually calling the method you think you are.

If you're setting the connections programmatically, breakpoint the addItemWithTitle: (or equivalent call) call and ensure that your NSMenuItem setup correctly immediately after stepping over that line.

---EDIT---

After looking over the posted code, there are several fundamental flaws with it, any of which could be causing the breakage under 10.6.

  1. First, you're confusing the role of a delegate in relation to the menu. The delegate should not be your NSMenu object, your delegate should be an object that is invoked as a "call back" by the NSMenuItem to provide custom logic. You need not be extending NSMenu at all, and your MenuTestAppDelegate should only be extended from NSObject.

  2. The class of your Menu object in your MainMenu.xib file is of type MenuTest, but you don't have a MenuTest class declared in your project. Hopefully this is merely a copy/paste error while you were setting up your test project, but you should check it out.

  3. I find it far easier to set up the NSStatusItem's menu programmatically. Try this:


// create the menu
- (void)createMenu
{   
    NSMenu* aMenu = [NSMenu new];
    [aMenu setDelegate:self];

    NSMenuItem* quitItem = [[NSMenuItem alloc] initWithTitle:@"quitItem"
                           action:@selector(quitSelected:) 
                           keyEquivalent:@""];

    [aMenu addItem:quitItem];

    NSStatusItem* statusItem = [[NSStatusBar systemStatusBar]
                               statusItemWithLength:NSVariableStatusItemLength];

    NSImage* itemImage = [[NSImage alloc] initWithContentsOfFile:
                         [[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"]];
    NSImage* itemAlternate = [[NSImage alloc] initWithContentsOfFile:
                             [[NSBundle mainBundle] pathForResource:@"alternate" ofType:@"png"]];

    [statusItem setImage:itemImage];
    [statusItem setAlternateImage:itemAlternate];

    [statusItem setHighlightMode:YES];
    [statusItem setMenu:aMenu];
}
Peter Nix
Thanks. I'm not adding these menu items programatically. I created the menu in IB. That these are not hooked up sounds very plausible, except that they are - the same binary functions fine on Leopard. Is there some scenario you know where something changed here from 10.5->10.6?
psychotik
@psychotik unfortunately, nothing specific for the case of 10.5 -> 10.6 breaking the interface. Just taking a best guess...
Peter Nix
I uploaded a simple repro - if you have the time, I'd appreciate you taking a look incase you can figure it out. It's about 20 lines of code + the xib.
psychotik
Peter, thanks for looking. #1 isn't standard but the menu item *is* an object so it should be fine, specially since 10.5 doesn't have a problem with it. I'll try using the more standard way and let you know if it helped. #2 is just a case of class name not matching file name. It wouldn't run on 10.5 otherwise. #3 is an interesting approach - certainly looks promising. I'll give these changes a shot. Thanks!
psychotik
Switching to using dynamic menus and not having a delegate for the menu in the designer seems to have done the trick. I was looking at some documentation around what's new in Menus in 10.6 and I found this new protocol which might have something to do with it - basically, the object you set as delegate needs to implement this interface, I believe - it is 10.6 only. http://developer.apple.com/mac/library/documentation/Cocoa/Reference/NSMenuDelegate_Protocol/Reference/Reference.html
psychotik