MenuItem Outlets from a different XIB File?

Discussion in 'Mac Programming' started by BadWolf13, Jun 13, 2010.

  1. BadWolf13 macrumors 6502

    Dec 17, 2009
    Ok, got a program with two XIB files. Now, I want something happening in my secondary XIB file to affect the "enabled" status of some of the menu items in MainMenu.XIB. I created 3 NSMenuItem outlets in the windowController subclass for my seconary XIB file in the hopes that I could connect them using FirstResponder. However, that's not working.

    Now I know I could move the outlets to the "Controller" class and use Notifications, but I'm wondering if there's a way to do this without notifications.

    So, does anyone have any suggestions, or do I have to do the notification thing.
  2. ritsard macrumors regular


    Jun 18, 2009
    SF Bay Area, CA
    You would want to look into using NSMenuValidation. It will validate each menuitem based on your requirements.
  3. BadWolf13 thread starter macrumors 6502

    Dec 17, 2009
    Thanks for the idea, but it's not working. The documentation says that the validateMenuItem method has to be placed in the target of the menu item in question. Here's the kicker, the target of these three methods is FirstResponder. Now I placed the validateMenuItem method in the same class that the responding methods are listed in, but the method isn't even being accessed by the program. Anything special I have to do in this case?
  4. Sydde macrumors 68020


    Aug 17, 2009
    For your future reference, in case you do not already understand what the First Responder in a xib file is, it is just a way to set the action of an object without setting its target: when you connect to First Responder, the target is set to nil, meaning the responder chain will be followed to find a target that responds to the action.

    Which raises the question: where are the action and validateMenuItem methods? Is the class in which they reside a descendent class of NSResponder? If not, you need to put them into a class that is, that is in the responder chain. Perhaps look at the documentation on the responder chain.
  5. BadWolf13 thread starter macrumors 6502

    Dec 17, 2009
    Thank you Sydde,

    I can confirm a couple of things for you. First, the class that contains the target actions for these menu items is a subclass of NSWindowController, so yes, it does inherit from NSResponder, and yes, it is in the responder chain. It is the same class that I put the validateMenuItems method into. I wash hoping that was the right choice, but when I placed a breakpoint into it, the program never reaches it.
  6. Sydde macrumors 68020


    Aug 17, 2009
    Well, I would just code the outlets. The code (if it is in the window controller) would look something like

    - (id)initWithWindowNibName:(NSString)windowNibName {
         NSMenu          *menuOfInterest
         [super initWithWindowNibName:windowNibName];
         // tagForMenu is defined in the .h file and set in IB
         menuOfInterest = [[[NSApp mainMenu] itemWithTag:tagForMenu] submenu];
         if ( nil != menuOfInterest ) {
              // tagForItem is defined in .h and set in IB
              // menuItemOutlet is an ivar
              menuItemOutlet = [menuOfInterest itemWithTag:tagForItem];
              // for as many outlets as you need to connect
    I always use tags to make it easier to localize and/or modify the app. You could put code similar this in an -awakeFromNib or -windowControllerDidLoadNib method in any object if it makes more sense to do that. Assuming you are writing a document-based application, the code that validates the menu probably should check to make sure it is the key window.
  7. BadWolf13 thread starter macrumors 6502

    Dec 17, 2009
    Thanks dude, I figured out how to fix my validateMenuItem method after all. I had it using an If based on the title of the menuItem, which for some reason didn't work. Changed it to use tags, such as below.

    -(BOOL)validateMenuItem:(NSMenuItem *)menuItem
    	NSLog(@"Validating Menu Item: %@", [menuItem title]);
    	if ([[self window] isKeyWindow]) {
    		ItemDetailsController *wc = [[self window] windowController];
    		if ([menuItem tag] == 42) {
    			return ![wc openForEditing];
    		if ([menuItem tag] == 43) {
    			return [wc openForEditing];
    	return YES;
    Now one question, if I wanted to define a constant like tagForMenu, instead of using straight numbers, how would I do that?
  8. kainjow Moderator emeritus


    Jun 15, 2000
    Easiest way is with #defines:

    #define MyMenuItemTag 42
    Then just use MyMenuItemTag wherever you'd use 42.

Share This Page