How to create Status Bar icon and menu in macOS using SwiftUI

Since this question received more attention lately, and the only reply doesn’t fully solve the issue I would like to repeat the edited part of my question and mark it as resolved.

Edit2: Added an additional piece of code that allows using a SwiftUI view as the status bar icon. Might be handy for displaying dynamic badges.

Found a way to show this in swiftui without an annoying NSPopover. Even though I used AppDelegate’s applicationDidFinishLaunching to execute the code, it can be called from any place of your app, even in a SwiftUI lifecycle app.

Here is the code:

func applicationDidFinishLaunching(_ aNotification: Notification) {
        // SwiftUI content view & a hosting view
        // Don't forget to set the frame, otherwise it won't be shown.
        //
        let contentViewSwiftUI = VStack {
            Color.blue
            Text("Test Text")
            Color.white
        }
        let contentView = NSHostingView(rootView: contentViewSwiftUI)
        contentView.frame = NSRect(x: 0, y: 0, width: 200, height: 200)
        
        // Status bar icon SwiftUI view & a hosting view.
        //
        let iconSwiftUI = ZStack(alignment:.center) {
            Rectangle()
                .fill(Color.green)
                .cornerRadius(5)
                .padding(2)
                
            Text("3")
                .background(
                    Circle()
                        .fill(Color.blue)
                        .frame(width: 15, height: 15)
                )
                .frame(maxWidth: .infinity, maxHeight: .infinity,  alignment: .bottomTrailing)
                .padding(.trailing, 5)
        }
        let iconView = NSHostingView(rootView: iconSwiftUI)
        iconView.frame = NSRect(x: 0, y: 0, width: 40, height: 22)
        
        // Creating a menu item & the menu to add them later into the status bar
        //
        let menuItem = NSMenuItem()
        menuItem.view = contentView
        let menu = NSMenu()
        menu.addItem(menuItem)
        
        // Adding content view to the status bar
        //
        let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
        statusItem.menu = menu
        
        // Adding the status bar icon
        //
        statusItem.button?.addSubview(iconView)
        statusItem.button?.frame = iconView.frame

        // StatusItem is stored as a property.
        self.statusItem = statusItem
    }

enter image description here

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)