Programmatically creating menus with Swift 3 and Cocoa
Asked Answered
S

1

8

I am trying my hand at creating a Cocoa GUI app programmatically (i.e. without a nib file) using Swift 3. I've run into trouble getting the application's menus to show.

I would expect the below code to show a File menu items on the menu bar. Instead, while the window launches and works as expected, the code to set the menu seems to have no effect:

import AppKit

final class ApplicationController: NSObject, NSApplicationDelegate {
    var mainWindow: NSWindow?

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        let mainMenu = NSMenu()
        let mainMenuFileItem = NSMenuItem(title: "File", action: nil, keyEquivalent: "")
        let fileMenu = NSMenu(title: "File")
        fileMenu.addItem(withTitle: "New...", action: nil, keyEquivalent: "n")
        mainMenuFileItem.submenu = fileMenu

        mainMenu.addItem(mainMenuFileItem)

        NSApp.mainMenu = mainMenu

        let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 800, height: 600),
                                            styleMask: [.titled, .closable, .resizable, .miniaturizable],
                                            backing: NSBackingStoreType.buffered, defer: false)
        window.orderFrontRegardless()
        window.title = "Hello World"
        self.mainWindow = window

        NSApp.activate(ignoringOtherApps: true)

    }

    func applicationWillTerminate(_ aNotification: Notification) {
        print("terminating")
    }

    func applicationShouldTerminateAfterLastWindowClosed(_ app: NSApplication) -> Bool{
        return true
    }
}

let app = NSApplication.shared()
let controller = ApplicationController()
app.delegate = controller

app.run()

The closest I've found to a working example is this answer. However, it appears to be for an earlier version of Swift/Cocoa, and I am not able to get that example working.

What am I doing wrong?

Sailesh answered 30/9, 2016 at 7:9 Comment(0)
S
2

One needs to call NSApp.setActivationPolicy(.regular) to make the application a "regular" one. Making that call before app.run() fixes the issue of no menu showing.

The "main" part of the code should thus be:

let app = NSApplication.shared()
NSApp.setActivationPolicy(.regular)
let controller = ApplicationController()
app.delegate = controller

app.run()
Sailesh answered 4/10, 2016 at 5:8 Comment(1)
According to my tests this is no longer needed. But my "main" looks very different, too.Shimmy

© 2022 - 2024 — McMap. All rights reserved.