3

My document-based app doesn't want these items, they aren't in my storyboard. They get inserted by the system via this call chain.

-[NSMenu insertItem:atIndex:] ()
-[NSMenu insertItemWithTitle:action:keyEquivalent:atIndex:] ()
-[NSApplication(NSMenuUpdating) _customizeFileMenuIfNeeded] ()
-[NSApplication(NSMenuUpdating) _customizeMainMenu] ()
-[NSApplication finishLaunching] ()
-[NSApplication run] ()
  NSApplicationMain ()
mr. fixit
  • 1,404
  • 11
  • 19

2 Answers2

4

The easy way is to NOT override +[NSDocument autosavesInPlace]. But in my case, I want autosave, so I do override that (returning YES), leaving me with the hard way:

In my app delegate's applicationDidFinishLaunching:, I call

- (void)removeUnwantedFileMenuItems
{
    NSMenu *fileMenu = NSApp.mainMenu.itemArray[1].submenu;

    void (^removeItemWithSelector)(SEL) = ^void(SEL selector) {
        NSInteger idx = [fileMenu indexOfItemWithTarget:nil andAction:selector];
        if (idx != -1)
        {
            [fileMenu removeItemAtIndex:idx];
        }
    };
    removeItemWithSelector(@selector(duplicateDocument:));
    removeItemWithSelector(@selector(moveDocument:));
    removeItemWithSelector(@selector(renameDocument:));
    removeItemWithSelector(@selector(saveDocumentAs:));
}
mr. fixit
  • 1,404
  • 11
  • 19
3

Swift 5 variant of mr. fixit's answer, to be placed in applicationDidFinishLaunching of the NSApp delegate:

if let fileMenu = NSApp.mainMenu?.items[1].submenu {
    for selector in [NSSelectorFromString("duplicateDocument:"),
                     NSSelectorFromString("moveDocument:"), 
                     NSSelectorFromString("renameDocument:"), 
                     NSSelectorFromString("saveDocumentAs:")] {
        let index = fileMenu.indexOfItem(withTarget: nil, andAction: selector)
        if index > -1 {
            fileMenu.removeItem(at: index)
        }
    }
}
Ely
  • 8,259
  • 1
  • 54
  • 67