Supporting Dark Mode
The gist of what I have to share comes from tackling challenge after challenge in my own apps. Some interfaces adapted effortlessly to Dark Mode, some needed only a little finessing, while others demanded relatively hard-core infrastructural changes.
My advice will focus on the dichotomy of Light Mode and Dark Mode. The Mac’s appearance support is more nuanced than that. NSAppearance supports a hierarchy of appearances that build upon one another. The light and dark modes are the two most prominent user-facing examples, but variations such as high contrast modes should also be considered.
These articles are loosely organized in order from more fundamental to more arcane, with a priority on establishing knowledge and techniques in earlier articles that you may need to reference in later articles.
Previously: Dark Side of the Mac: Appearance & Materials.
Update (2018-10-09): Howard Oakley:
Dark Mode seems so simple, but turns out to be a lot more complex. Every so often I turn over a fresh stone in Mojave’s otherwise excellent implementation, and discover another crab waiting to bite.
In Mojave, TextEdit follows Apple’s standard protocol of fixing its text display in Light Mode. When you switch to Dark Mode, the window and its controls go dark, but the view in which the document’s text is displayed remains obstinately black on white. That may be fine when you’re working on plain Rich Text, if that’s not a contradiction. But several of my tools here, like Consolation 3 and Nalaprop, now generate multicoloured Rich Text, which looks drop-dead gorgeous in Dark Mode.
2 Comments RSS · Twitter
Just in case, when it comes to semantic colors and old OS X versions (i.e. < 10.10), it's possible to use the labelColor, secondaryLabelColor, etc. methods as-is thanks to Obj-C categories, load method and runtime.
https://github.com/packagesdev/packages/blob/master/AppKit%20%2B%20Extensions/NSColor%2BLabelColor.h
https://github.com/packagesdev/packages/blob/master/AppKit%20%2B%20Extensions/NSColor%2BLabelColor.m
This eliminates the need to have if ([NSColor class] respondsToSelector: ...]). in multiple places.