Search code examples
swiftmacoscocoaappdelegate

How can I create mainMenu and menu items in AppDelegate for Cocoa macOS?


I am trying build my mainMenu from AppDelegate, I already did disconnect my Storyboard file and I am using a main.swift file for loading my app as @mainI tried this codes for building my menu, but it does not work, the function does not create my items, also I got no error or issue, I think the created menu cannot plugged to my app.

my main.swift file:

 import Cocoa

// 1
let app = NSApplication.shared
let delegate = AppDelegate()
app.delegate = delegate

// 2
_ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv)

import Cocoa
import SwiftUI

class AppDelegate: NSObject, NSApplicationDelegate {

    private var window: NSWindow!

    func applicationDidFinishLaunching(_ aNotification: Notification) {

        window = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
            styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
            backing: .buffered, defer: false)
        
        window.center()
        window.setFrameAutosaveName("Main Window")
        window.title = "No Storyboard Window"
        window.contentView = NSHostingView(rootView: ContentView())
        window.makeKeyAndOrderFront(nil)
        
        customMainMenu()
 
    }
    
    
    func customMainMenu() {
        
        if let appMainMenu = NSApp.mainMenu {
            
            let mainMenu = NSMenuItem()
            mainMenu.submenu = NSMenu(title: "MainMenu")

            let mainMenuItem1 = NSMenuItem(title: "Close", action: #selector(NSWindow.performClose(_:)), keyEquivalent: "w")
            mainMenuItem1.keyEquivalentModifierMask = .command

            let mainMenuItem2 = NSMenuItem(title: "Quit", action: #selector(NSApplication.shared.terminate(_:)), keyEquivalent: "q")
            mainMenuItem2.keyEquivalentModifierMask = .command
            

            mainMenu.submenu?.items = [mainMenuItem1, mainMenuItem2]
            appMainMenu.items = [mainMenu]
            
        }
    }
 
}

Solution

  • The following source code will create a basic menu for swift. To run in Xcode create a Swift project and delete the contents of the AppDelegate file and replace it with the following. Then change the name of the AppDelegate.swift file to main.swift and run. The window is already closable so I didn't add a redundant menu item for this.

    import Cocoa
    
    // **** App Delegate **** //
    class AppDelegate: NSObject, NSApplicationDelegate {
     var window: NSWindow!
    
    func buildMenu() {
    
     let mainMenu = NSMenu()
     NSApp.mainMenu = mainMenu
    // **** App menu **** //
     let appMenuItem = NSMenuItem()
     mainMenu.addItem(appMenuItem)
     let appMenu = NSMenu()
     appMenuItem.submenu = appMenu
     appMenu.addItem(withTitle:"Quit", action:#selector(NSApplication.terminate), keyEquivalent: "q")
    }
        
    func buildWnd() {
        
    let _wndW = CGFloat (440)
    let _wndH = CGFloat (300)
    // **** Window **** //
    window = NSWindow(contentRect:NSMakeRect(0,0,_wndW,_wndH),styleMask:[.titled, .closable, .miniaturizable, .resizable], backing:.buffered, defer:false)
    window.center()
    window.title = "Swift Test Window"
    window.makeKeyAndOrderFront(window)
    }
     
    func applicationDidFinishLaunching(_ notification: Notification) {
     buildMenu()
     buildWnd()
    }
    
    }
    let appDelegate = AppDelegate()
    
    // **** Main **** //
    let application = NSApplication.shared
    application.delegate = appDelegate
    application.run()