setEnabled doesn't work on an NSMenuItem


Google didn't turn up anything and posting here proved fruitful yesterday, so I'll try it again.

In my program I have some menu items. At times I need some of the menu items to be disabled and then later reenabled (using them doesn't cause crashes, but the behavior is confusing and easier to just avoid letting users at it, especially when the menu item doesn't do anything due to the current state of the application). Alas, it won't work.

For example, in my awakeFromNib method, I have the following line:

[stop_menu setEnabled: NO];

I tested it and before this line [stop_menu isEnabled] returns 1 and afterwards returns 0. But, this change is not reflected in the GUI.

At the same time, I have controls all over the window being enabled and disabled during the life of the application without any problems. It's just the menu that's having problems.

Any ideas on what might be up with this? Is there some function to refresh the menu that has to be called? Any help would be greatly appreciated.


I've had the problem too. The main NSMenu auto enables all it's menu items. So even if you set a menu to be disabled manually, it's automatically enabled by the menu. I tried turning off autoenabling before, but that didn't seem to work. There's probably a delegate of NSMenu (I never looked, at the time I didn't even understand how delegates work) which can determine if menus should be enabled or not. If not, the only way I know how to do it is to remove and reset the menuitems selector. If it doesn't have a correct NSSelector, then the menu item won't be enables. I think just removing, readding the target does the same thing. This is a really hacky way of making it work, but it's the only way I know how.



that's quite easy actually. set autoenables to no: [myMainMenu setAutoenablesItems:NO] and implement

- (BOOL)validateMenuItem:(NSMenuItem *)menuItem

in ib, make all menuitems you want control over outlets and voilà, you can simply compare the menu item given to you by the runtime to your menuitems and return yes or no:
if (menuItem == mySpecialMenuItem)
	if (conditionForMenuItemSpecialItem)
		return YES;
	} else {
		return NO;

whenever the condition changes, just call [myMainMenu update] and the new state will be reflected.

hope that helps.


Originally posted by seb2
that's quite easy actually.


hope that helps.

Thanks, that did the trick. It's so obvious, I must have just missed where it is in the documentation. Oh well. %-)