Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How i can get the Application Menu in Cocoa

How can I get the NSMenu or NSMenuItem for the application menu (the one in the menu bar next to the apple menu). It seems to be automatically created and independent from the NSMenu I set via NSApplication setMainMenu.

By the way: I'm building my complete application without Xcode, so please no InterfaceBuilder tips.

PS: MacOSX 10.5

like image 844
Lothar Avatar asked Aug 08 '10 22:08

Lothar


4 Answers

Without IB, you can access the menu using the NSApplication's mainMenu:

NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu];
NSMenu *appMenu = [[mainMenu itemAtIndex:0] submenu];

for (NSMenuItem *item in [appMenu itemArray]) {
    NSLog(@"%@", [item title]);
}
like image 78
Jarret Hardie Avatar answered Nov 07 '22 11:11

Jarret Hardie


Though this is 5 years old question... I like to share how to make it.

In my experience in OS X 10.11 (El Capitan) with Xcode 7.1, it's not hard to replicate that application menu. It seems Apple removed all the weird limitations.

Note: This code is updated for Swift 3, and tested only in macOS Sierra (10.12.1).

//
//  AppDelegate.swift
//  Editor6MainMenuUI2Testdrive
//
//  Created by Hoon H. on 2016/11/05.
//  Copyright © 2016 Eonil. All rights reserved.
//

import Cocoa

/// You SHOULD NOT use `@NSApplicationMain` 
/// to make your custom menu to work.
class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ aNotification: Notification) {}
    func applicationWillTerminate(_ aNotification: Notification) {}
}

func makeMainMenu() -> NSMenu {
    let mainMenu            = NSMenu() // `title` really doesn't matter.
    let mainAppMenuItem     = NSMenuItem(title: "Application", action: nil, keyEquivalent: "") // `title` really doesn't matter.
    let mainFileMenuItem    = NSMenuItem(title: "File", action: nil, keyEquivalent: "")
    mainMenu.addItem(mainAppMenuItem)
    mainMenu.addItem(mainFileMenuItem)

    let appMenu             = NSMenu() // `title` really doesn't matter.
    mainAppMenuItem.submenu = appMenu

    let appServicesMenu     = NSMenu()
    NSApp.servicesMenu      = appServicesMenu

    appMenu.addItem(withTitle: "About Me", action: nil, keyEquivalent: "")
    appMenu.addItem(NSMenuItem.separator())
    appMenu.addItem(withTitle: "Preferences...", action: nil, keyEquivalent: ",")
    appMenu.addItem(NSMenuItem.separator())
    appMenu.addItem(withTitle: "Hide Me", action: #selector(NSApplication.hide(_:)), keyEquivalent: "h")
    appMenu.addItem({ () -> NSMenuItem in
        let m = NSMenuItem(title: "Hide Others", action: #selector(NSApplication.hideOtherApplications(_:)), keyEquivalent: "h")
        m.keyEquivalentModifierMask = [.command, .option]
        return m
        }())
    appMenu.addItem(withTitle: "Show All", action: #selector(NSApplication.unhideAllApplications(_:)), keyEquivalent: "")

    appMenu.addItem(NSMenuItem.separator())
    appMenu.addItem(withTitle: "Services", action: nil, keyEquivalent: "").submenu = appServicesMenu
    appMenu.addItem(NSMenuItem.separator())
    appMenu.addItem(withTitle: "Quit Me", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")

    let fileMenu = NSMenu(title: "File")
    mainFileMenuItem.submenu = fileMenu
    fileMenu.addItem(withTitle: "New...", action: #selector(NSDocumentController.newDocument(_:)), keyEquivalent: "n")

    return mainMenu
}

let del = AppDelegate()
/// Setting main menu MUST be done before you setting app delegate.
/// I don't know why.
NSApplication.shared().mainMenu = makeMainMenu()
NSApplication.shared().delegate = del
NSApplication.shared().run()

Anyway, it is not being generated automatically, and I had to set them all up myself. I am not sure whether there is another way to do this or not.

You can download working example here.

like image 37
eonil Avatar answered Nov 07 '22 12:11

eonil


my two cents for Swift 5.0

private final func manageMenus(){
    let  mainMenu =  NSApplication.shared.mainMenu

    if let editMenu = mainMenu?.item(at: 1)?.submenu{
        for item in editMenu.items{
            print(item.title)
        }
    }
}

so You can also enable it:

....

  for item in editMenu.items{
       item.isEnabled = true
   }
like image 5
ingconti Avatar answered Nov 07 '22 11:11

ingconti


Making a Cocoa app without Xcode or IB sounds masochistic to me, but to each his own... Try this: [[[NSApp mainMenu] itemAtIndex: 0] submenu].

like image 1
JWWalker Avatar answered Nov 07 '22 12:11

JWWalker