A recent conversation I had with Jeff Johnson (of ClickToFlash fame, @lapcatsoftware on twitter) prompted me to look into how badging an app’s icon in macOS’ Dock works.
There were a couple of questions that needed answering:
- Does badging happen automatically when sending an NSUserNotification?
- If not, how do I apply a badge to my app’s icon in the first place?
- How do I retrieve and respect the user’s Notification settings for the app in System Preferences?
Automatic Badging by Sending a NSUserNotification?
Nope, automatic badging doesn’t happen. Even though System Preferences -> Notifications suggests that badges and notifications belong together, in code, they’re separated.
That means you have to add the badge to your app’s icon yourself. Also, you need to keep track of whatever number you want to display with the badge and update or clear it at appropriate times.
For example, Mail.app uses the badge to display the amount of unread eMails you have. The badge doesn’t clear when you activate Mail and only decreases when you mark mails as read.
Transmission, on the other hand, informs you about how many downloads have finished since you last had the app active. Once you activate the app again, the badge gets cleared and re-starts from zero.
How to Badge the App’s Icon?
Badging is straightforward:
NSApp.dockTile.badgeLabel = @"Badge";
Please note that putting text into the badge is not a good idea – I did it here just for fun, but text in the badge is very limited and if you have a longer string, what you’ll end up with is something like “A….z”.
It’s best to stick with numbers.
Respecting System Preferences’ Notifications Settings?
If you only use badges (without notifications), you’ll notice your app is missing from System Preferences’ Notifications preference pane.
That can pose a problem, because now you either have to create your own user-setting for badges or the user will have no way of turning them off.
The trick, then, lies with NSUserNotification. Not in the API itself, but in two crucial steps:
- Code sign your app.
- Add this key-value pair to your Info.plist: NSUserNotificationAlertStyle with a string value of either banner (recommended by Apple) or alert.
Supposedly, there’s another value, none, but that hasn’t worked for me yet – the app won’t appear in the Notifications preference pane.
Having the key-value pair in your Info.plist has no downside if you don’t use NSUserNotifications. There’s only the upside of having the user be able to disable your app’s badges if they like.
Now that the user can change the setting for your app’s badges, how do you read it out to see if you should badge or not? It’s easier than you think: you don’t.
Just like the system doesn’t show your NSUserNotifications if the user has disabled them for your app, the Dock simply doesn’t display your badge if the user has disabled it in System Preferences.
All you have to do is keep track of the number that should be displayed in the badge, and that you update or clear it at appropriate times.
For example, you might not want to have the badge visible when the user quits your app, so you could set -badgeLabel to nil in -applicationWillTerminate:.
By the way, if you ever need to reset System Preferences – Notifications for your app (or all apps), there’s a nice how-to on stackoverflow.
Happy badging :)
Update: Jeff Johnson follows up with some more tips and tricks about NSUserNotification in this blog post.
– – – Do you enjoy my blog and/or my software? – – –
Stay up-to-date on all things Eternal Storms Software and join my low-frequency newsletter (one mail a month at most).
Thank you :)