Search code examples
objective-cmacosappearancemacos-mojave

How can dark mode be detected on macOS 10.14?


In macOS 10.14 users can choose to adopt a system-wide light or dark appearance and I need to adjust some colours manually depend of the current mode.


Solution

  • Since the actual appearance object you usually get via effectiveAppearance is a composite appearance, asking for its name directly probably isn't a reliable solution.

    Asking for the currentAppearance usually isn't a good idea, either, as a view may be explicitly set to light mode or you want to know whether a view is light or dark outside of a drawRect: where you might get incorrect results after a mode switch.

    The solution I came up with looks like this:

    BOOL appearanceIsDark(NSAppearance * appearance)
    {
        if (@available(macOS 10.14, *)) {
            NSAppearanceName basicAppearance = [appearance bestMatchFromAppearancesWithNames:@[
                NSAppearanceNameAqua,
                NSAppearanceNameDarkAqua
            ]];
            return [basicAppearance isEqualToString:NSAppearanceNameDarkAqua];
        } else {
            return NO;
        }
    }
    

    You would use it like appearanceIsDark(someView.effectiveAppearance) since the appearance of a specific view may be different than that of another view if you explicitly set someView.appearance.

    You could also create a category on NSAppearance and add a - (BOOL)isDark method to get someView.effectiveAppearance.isDark (better chose a name that is unlikely to be used by Apple in the future, e.g. by adding a vendor prefix).