View Full Version : How to change menu items and window name based on target_name

Jun 9, 2009, 09:20 AM
I have a Cocoa project that has two targets, WebDrive and GroupDrive. The functionality is the same, but the product name changes based on how it's built.

I have one MainMenu.xib file that has all my resources in it; menu, main window, etc, they all say WebDrive.

I would like that to change based on which target is built, or I would like to change it dynamically at runtime.

In the main awakeFromNib I tried

[[NSApp mainWindow] setTitle:@"GroupDrive"];
[[NSApp mainWindow] setTitle:@"WebDrive"];

but that did not update the main window Title.

Is there some way in IB to use ${TARGET_NAME} or ${PRODUCT_NAME} in the menus or window titles to have them set automatically?


Jun 9, 2009, 09:27 AM
You could use [[NSProcessInfo processInfo] processName] to get the name, or read it from the .app's info.plist file (through NSBundle). I would suggest not using [NSApp mainWindow], but instead do this in your window's controller and call [self window] instead.

For the menus, you could leave them as they are in the original nib, and then loop through each menu and its menu items, finding ones with a certain tag in their title and replacing that with your app name.

Jun 9, 2009, 02:12 PM
Prolly the easiest and non-code way is to just make two sets of XIB files, with the different names in them. Put them in two different folders that you name logically so you can distinguish which set is which.

In your active target you can edit the "Copy Bundle Resources" phase and add the correct set of XIBs. Or in the file list in the editor window (that view that slides down above the text editor view) un/check the XIBs that only apply to the specific target.

This is the whole point of keeping UI elements and translatable text in discrete files; you can edit them to match the user's default language or to change the name based on use (if you make one app that is customized for different customers or project names).

Jun 9, 2009, 05:08 PM
I'm trying to enumerate the menu to replace the item titles and it seems that I just get the raw system menu. The following code fetches...

NSMenu* pMenu = [NSApp mainMenu];

2009-06-09 18:04:25.975 GroupDrive[216:813] <NSMenu: 0x151370>
Title: AMainMenu
Supermenu: 0x0 (None), autoenable: YES, change messages enabled: YES
Items: (
<MenuItem: 0x1513d0 , submenu: 0x1465e0 (Apple)>,
<MenuItem: 0x151450 File, submenu: 0x1487f0 (File)>,
<MenuItem: 0x1514d0 Edit, submenu: 0x14e3c0 (Edit)>,
<MenuItem: 0x151550 Format, submenu: 0x1515d0 (Format)>,
<MenuItem: 0x1517c0 View, submenu: 0x14f550 (View)>,
<MenuItem: 0x151840 Window, submenu: 0x150250 (Window)>,
<MenuItem: 0x1512f0 Help, submenu: 0x14d8e0 (Help)>

I should see the main WebDrive menu between (Apple) and (File).

Jun 9, 2009, 05:50 PM
Btw, I did manage to get the Title updating correctly. I derived my own class from NSWindow and then in the awakeFromNib I issued a call to setTitle using the CFBundleName from the main bundle.

Jun 9, 2009, 06:22 PM
Ok, I figured it out. Here's some code that will traverse a menu and substitute text:

if ( myMenu )
NSString* strOld = @"Old";
NSString* strNew = @"New";

int iCount = [myMenu numberOfItems];
for ( int i=0; i<iCount; i++ )
NSMenuItem* pItem = [myMenu itemAtIndex:i];
if ( pItem )
NSString* str = [pItem title];
[pItem setTitle:[str stringByReplacingOccurrencesOfString:strOld withString:strNew]];
[self fixupMenu:[pItem submenu]];//process submenu

Thanks for the help folks!