Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a menu bar SwiftUI app for MacOS Big Sur

I'm trying to create an app that only appears in the MacOS Big Sur menu bar (top right corner) by following this tutorial: https://medium.com/@acwrightdesign/creating-a-macos-menu-bar-application-using-swiftui-54572a5d5f87/. It worked on Xcode 11 and MacOS Catalina because there was an AppDelegate.swift file, but I've heard that this was replaced by this method:

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

However, the first few steps of the tutorial require that I make several changes to the (now non-existant) AppDelegate.swift file. I've tried making these changes in MyApp.swift, but I can't seem to get it to work. Is anyone willing to help me adapt that tutorial for MacOS Big Sur/Xcode 12?

Note: here's how the AppDelegate.swift file was supposed to look (if it existed) according to the tutorial (if you don't want to open the tutorial for whatever reason):

import Cocoa
import SwiftUI

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var popover: NSPopover!
    var statusBarItem: NSStatusItem!
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Create the SwiftUI view that provides the window contents.
        let contentView = ContentView()

        // Create the popover
        let popover = NSPopover()
        popover.contentSize = NSSize(width: 400, height: 500)
        popover.behavior = .transient
        popover.contentViewController = NSHostingController(rootView: contentView)
        self.popover = popover
        
        // Create the status item
        self.statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))
        
        if let button = self.statusBarItem.button {
            button.image = NSImage(named: "Icon")
            button.action = #selector(togglePopover(_:))
        }
    }
    
    @objc func togglePopover(_ sender: AnyObject?) {
        if let button = self.statusBarItem.button {
            if self.popover.isShown {
                self.popover.performClose(sender)
            } else {
                self.popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
            }
        }
    }
    
}
like image 233
Rohan Avatar asked Nov 13 '20 05:11

Rohan


People also ask

How do I make my Big Sur Mac menu bar dark?

Luckily, reverting to the traditional opaque menu bar is simple. Open System Preferences > Accessibility > Display and select Reduce Transparency.


Video Answer


1 Answers

In your App scene, use NSApplicationDelegateAdaptor property wrapper to tell SwiftUI it should use your AppDelegate class for the application delegate. So your App class should look like this:

@main
struct MyApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Knowledge base link

like image 100
alex1704 Avatar answered Oct 23 '22 22:10

alex1704