Dynamically toggle visibility of macOS app’s dock icon
Dynamically toggle visibility of macOS app’s dock icon
Show and hide a macOS app's dock icon at runtime by switching its activation policy – without losing window focus or keyboard input.
Some macOS apps live in the menu bar but still want an optional dock icon – a preference power users can flip on or off. The catch: changing the dock icon at runtime tends to steal focus, drop the app's window, or leave a duplicate icon behind. Here's the approach I settled on.
macOS derives the dock icon from the app's activation policy: .regular shows it, .accessory hides it. Toggling the icon is really just switching between the two:
extension NSApplication {
static func toggleActivationPolicy() {
let current = NSApp.activationPolicy()
let next: NSApplication.ActivationPolicy = current == .regular ? .accessory : .regular
NSApp.setActivationPolicy(next)
// Switching to .accessory deactivates the app – bring it back.
if next == .accessory { NSApp.activate() }
}
}
Three details make it behave:
Mark the app as an agent. Add Application is agent (UIElement) = YES to Info.plist so it can start without a dock icon.
Launch without stealing focus. Set .prohibited in applicationWillFinishLaunching, then your real policy in applicationDidFinishLaunching – and open the window yourself, since .prohibited stops SwiftUI from doing it for you.
Debounce the toggle. The dock's show/hide animation takes a moment; flip faster than that and you can end up with two icons. A ~150 ms guard between toggles avoids it.
Through all of this the window keeps keyboard focus, so shortcuts keep firing while the icon comes and goes. Full sample on GitHub:
A SwiftUI sample that toggles the dock icon at runtime.
It's the runtime companion to Fine-Tuning macOS App Activation Behavior, which covers these activation policies in depth.