2010-08-08 23 views
10

¿Cómo puedo obtener NSMenu o NSMenuItem para el menú de la aplicación (el que está en la barra de menú al lado del menú de la manzana). Parece que se crea automáticamente y es independiente del NSMenu que establecí a través de NSApplication setMainMenu.Cómo puedo obtener el menú de la aplicación en Cocoa

Por cierto: estoy compilando mi aplicación completa sin Xcode, así que no le dé consejos a InterfaceBuilder.

PS: MacOSX 10.5

Respuesta

17

Sin IB, se puede acceder al menú usando mainMenu del NSApplication:

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

for (NSMenuItem *item in [appMenu itemArray]) { 
    NSLog(@"%@", [item title]); 
} 
+0

No, esto no funciona. numberOfItems en NSMenu también me da 1 cuando veo claramente los elementos de "TestMenu File" en la barra de menú. – Lothar

+0

Ah, parece que hice una suposición sobre la estructura de su proyecto. ¿Creó el proyecto en XCode y luego eliminó el nib/xib por completo? ¿O estás yendo totalmente desde cero? Esta entrada de blog habla sobre lo que estás experimentando con mainMenu y cómo podrías trabajar tu proyecto de tal forma que puedas acceder al menú de la aplicación: http://lapcatsoftware.com/blog/2007/05/16/working -without-a-nib-part-1/ –

+0

Gracias, eso es todo. Y sí, no tengo nada, de hecho, durante el desarrollo incluso corro como un programa ELF a.out normal sin una estructura Bundle. Funciona bien, excepto para el menú. – Lothar

0

Hacer una aplicación de cacao sin Xcode o IB suena masoquista para mí, pero a cada uno lo suyo ... Prueba esto: [[[NSApp mainMenu] itemAtIndex: 0] submenu].

+0

Bueno, estoy escribiendo un enlace de idioma y quiero mantener la plataforma portátil. Pero tu solución no funciona. El elemento del menú con el nombre del paquete que se autogenera no es parte del mainMenu. – Lothar

+0

Me funcionó, pero lo probé en una aplicación normal con Xcode e IB. – JWWalker

+0

¿Es posible que lo haya probado demasiado pronto en el proceso de inicio de la aplicación? Lo intenté en el método de delegado 'applicationDidFinishLaunching:'. – JWWalker

11

Aunque esto es de 5 años de edad pregunta ... Me gusta compartir la manera de hacerlo.

En mi experiencia en OS X 10.11 (El Capitan) con Xcode 7.1, no es difícil replicar ese menú de aplicaciones. Parece que Apple eliminó todas las limitaciones extrañas.

Nota: Este código se actualiza para Swift 3, y se prueba solo en 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() 

De todos modos, no se genera automáticamente, y tuve que configurarlo todo yo mismo. No estoy seguro si hay otra manera de hacer esto o no.

Puede descargar el ejemplo de trabajo here.

Cuestiones relacionadas