cd /news/developer-tools/quickmacapp · home topics developer-tools article
[ARTICLE · art-12060] src=gist.github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

QuickMacApp

The article provides Swift code for running any SwiftUI view as a standalone macOS application. It defines an `NSApplication` extension with a `run` method that sets up a custom menu bar and creates an `AppDelegate` to manage the window and hosting view. The code is inspired by minimalist Cocoa programming techniques.

read3 min views23 publishedMay 15, 2020

Last active May 23, 2026 17:58

Star (190)You must be signed in to star a gist - Fork (31)You must be signed in to fork a gist

Save chriseidhof/26768f0b63fa3cdf8b46821e099df5ff to your computer and use it in GitHub Desktop.

QuickMacApp

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters| // Run any SwiftUI view as a Mac app. | | | import Cocoa | | | import SwiftUI | | | NSApplication.shared.run { | | | VStack { | | | Text("Hello, World") | | | .padding() | | | .background(Capsule().fill(Color.blue)) | | | .padding() | | | } | | | .frame(maxWidth: .infinity, maxHeight: .infinity) | | | } | | | extension NSApplication { | | | public func run<V: View>(@ViewBuilder view: () -> V) { | | | let appDelegate = AppDelegate(view()) | | | NSApp.setActivationPolicy(.regular) | | | mainMenu = customMenu | | | delegate = appDelegate | | | run() | | | } | | | } | | | // Inspired by https://www.cocoawithlove.com/2010/09/minimalist-cocoa-programming.html | | | extension NSApplication { | | | var customMenu: NSMenu { | | | let appMenu = NSMenuItem() | | | appMenu.submenu = NSMenu() | | | let appName = ProcessInfo.processInfo.processName | | | appMenu.submenu?.addItem(NSMenuItem(title: "About (appName)", action: #selector(NSApplication.orderFrontStandardAboutPanel(:)), keyEquivalent: "")) | | | appMenu.submenu?.addItem(NSMenuItem.separator()) | | | let services = NSMenuItem(title: "Services", action: nil, keyEquivalent: "") | | | self.servicesMenu = NSMenu() | | | services.submenu = self.servicesMenu | | | appMenu.submenu?.addItem(services) | | | appMenu.submenu?.addItem(NSMenuItem.separator()) | | | appMenu.submenu?.addItem(NSMenuItem(title: "Hide (appName)", action: #selector(NSApplication.hide(:)), keyEquivalent: "h")) | | | let hideOthers = NSMenuItem(title: "Hide Others", action: #selector(NSApplication.hideOtherApplications(:)), keyEquivalent: "h") | | | hideOthers.keyEquivalentModifierMask = [.command, .option] | | | appMenu.submenu?.addItem(hideOthers) | | | appMenu.submenu?.addItem(NSMenuItem(title: "Show All", action: #selector(NSApplication.unhideAllApplications(:)), keyEquivalent: "")) | | | appMenu.submenu?.addItem(NSMenuItem.separator()) | | | appMenu.submenu?.addItem(NSMenuItem(title: "Quit (appName)", action: #selector(NSApplication.terminate(:)), keyEquivalent: "q")) | | | let windowMenu = NSMenuItem() | | | windowMenu.submenu = NSMenu(title: "Window") | | | windowMenu.submenu?.addItem(NSMenuItem(title: "Minmize", action: #selector(NSWindow.miniaturize(:)), keyEquivalent: "m")) | | | windowMenu.submenu?.addItem(NSMenuItem(title: "Zoom", action: #selector(NSWindow.performZoom(:)), keyEquivalent: "")) | | | windowMenu.submenu?.addItem(NSMenuItem.separator()) | | | windowMenu.submenu?.addItem(NSMenuItem(title: "Show All", action: #selector(NSApplication.arrangeInFront(:)), keyEquivalent: "m")) | | | let mainMenu = NSMenu(title: "Main Menu") | | | mainMenu.addItem(appMenu) | | | mainMenu.addItem(windowMenu) | | | return mainMenu | | | } | | | } | | | class AppDelegate<V: View>: NSObject, NSApplicationDelegate, NSWindowDelegate { | | | init(_ contentView: V) { | | | self.contentView = contentView | | | } | | | var window: NSWindow! | | | var hostingView: NSView? | | | var contentView: V | | | func applicationDidFinishLaunching(_ notification: 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") | | | hostingView = NSHostingView(rootView: contentView) | | | window.contentView = hostingView | | | window.makeKeyAndOrderFront(nil) | | | window.delegate = self | | | NSApp.activate(ignoringOtherApps: true) | | | } | | | } |

Thanks

How it use with

var body: some Scene {
        WindowGroup {
             // ...
        }
  }

?

── more in #developer-tools 4 stories · sorted by recency
── more on @swiftui 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/quickmacapp] indexed:0 read:3min 2020-05-15 ·