The macOS status bar is a powerful and convenient place to display essential information or provide quick access to your app’s functionality. By default, the status bar displays a standard system icon, but sometimes you may want to create a more customized experience by using your own views. In this blog post, we’ll walk you through how to use a custom view on the status bar in macOS using Swift and SwiftUI.
Prerequisites
Before we get started, make sure you have the following:
- Xcode installed on your macOS machine.
- Basic knowledge of Swift and SwiftUI.
Creating the Project
Let’s start by creating a new macOS app project in Xcode:
- Open Xcode and choose “Create a new Xcode project.”
- Select “macOS” as the platform and choose the “App” template.
- Name your project and set the desired options.
- Click “Create” to generate the project.
Setting Up the Project
After creating the project, open the AppDelegate.swift
file. This is where we’ll implement the custom status bar view. The provided code sets up a custom status bar view that shows a dummy SwiftUI view, but you can replace it with your custom view later on.
Example code
import Cocoa
import SwiftUI
@main
class AppDelegate: NSObject, NSApplicationDelegate {
private var popover: NSPopover!
private var statusBarItem: NSStatusItem!
// hide the main Window when app start and create the bar UI
func applicationDidFinishLaunching(_ aNotification: Notification) {
NSApp.setActivationPolicy(.prohibited)
NSApp.hide(nil)
setupUI()
}
// create the bar UI
private func setupUI() {
// use NSHostingView to pass a SwiftUI view
let iconView = NSHostingView(rootView: DummyView())
// size must be defined
iconView.frame = NSRect(x: 0, y: 0, width: 120, height: 22)
statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))
// add a right click action
statusBarItem.button?.action = #selector(toggleMenu(_:))
statusBarItem.button?.sendAction(on: [.rightMouseDown])
statusBarItem.button?.addSubview(iconView)
statusBarItem.button?.frame = iconView.frame
}
// the right-click action
@objc func toggleMenu(_ sender: Any?) {
let event = NSApp.currentEvent!
if event.type == .rightMouseDown {
statusBarItem.menu = constructMenu()
let pos = NSPoint(x: statusBarItem.button!.bounds.origin.x, y: statusBarItem.button!.bounds.origin.y + statusBarItem.button!.bounds.size.height + 5)
statusBarItem.menu!.popUp(positioning: nil, at: pos, in: statusBarItem.button)
}
statusBarItem.menu = nil
statusBarItem.button!.action = #selector(toggleMenu(_:))
}
// create your right-click menu
func constructMenu() -> NSMenu {
let menu = NSMenu()
menu.addItem(NSMenuItem(title: "Quit", action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q"))
return menu
}
}
Understanding the Code
Let’s go through the important parts of the code:
setupUI()
: This function is responsible for setting up the custom view on the status bar. It creates an instance ofNSHostingView
with the root SwiftUI view (DummyView()
in this case) and adds it to the status bar.toggleMenu(_:)
: This function handles the right-click event on the status bar. When the user right-clicks on the status bar, it constructs a menu and displays it just below the custom view. TheconstructMenu()
function creates a simple menu with a “Quit” option, which allows the user to terminate the app.constructMenu()
: This function creates and returns a simpleNSMenu
with a “Quit” option that callsNSApplication.terminate(_:)
when selected.
DummyView example content
struct DummyView: View {
var body: some View {
HStack {
Text("Hello, World!")
Image(systemName: "car")
}
}
}
Replacing the Dummy View
To create your own custom view on the status bar, you need to replace the DummyView()
in the setupUI()
function with your SwiftUI view. You can create any SwiftUI view with your desired content, style, and behavior. The size of the view should fit within the status bar’s limits.
You can play and draw any kind of small apps, for instance my Formula-1 tracker 😉 or another funny case like the Mouse Odometer:
Conclusion
Using a custom view on the macOS status bar can enhance the user experience and provide quick access to essential features of your app. With Swift and SwiftUI, implementing a custom view on the status bar becomes straightforward and flexible. By following the steps in this blog post, you should now be able to integrate your own custom view into the status bar of your macOS app. Happy coding!