Quick guide on supporting Dark Mode on iOS

Since iOS 13, users can choose between a system-wide light or dark appearance. This post provides you with a quick guide to supporting Dark Mode in your app.

If you don’t want to support Dark Mode for now, you can scroll directly to the Good to know section.

Dark Mode… that’s my thing.

Basics

Prior to iOS 13, a color on iOS had one fixed value. Now, Apple introduced so called semantic colors.

  1. Semantic colors are dynamic, that means they can have multiple values. When the user selects a different style mode, a semantic color changes it’s value.
  2. Semantic colors are named after it’s purpose, not after the color itself. Apple predefined a lot of semantic colours like label, systemBackground, secondarySystemBackground etc. But you can also define your own semantic colours.

How does the system know what color to use?

Each view and view controller has it’s own UITraitCollection where you can check the userInterfaceStyle property. It can be set to .dark, .light or unspecified. You will learn more about this in later sections, let’s look at how to implement the dark mode support first.

Implementing Dark Mode

Colors

There are two possibilities how you can define and use colors in iOS: In code or via the asset catalog.

Defining colors in code

If you prefer to define your colors in code, you will need to define semantic colors instead of fixed color values to support dark mode.

I usually define all colors for a project in a struct like this:

struct Colors {
    static let error = UIColor(red: 198/255, green: 13/255, blue: 0/255, alpha: 1.0)
}

If you also have a similar centralized file where you define all your colors, supporting dark mode is really easy. All you need to do is to change the color definitions to the following:

static var error: UIColor {
    let light = UIColor(red: 198/255, green: 13/255, blue: 0/255, alpha: 1.0)
    let dark = UIColor(red: 242/255, green: 16/255, blue: 0/255, alpha: 1.0)

    guard #available(iOS 13, *) else { return light }
    return UIColor { traitCollection -> UIColor in
        return (traitCollection.userInterfaceStyle == .dark) ? dark : light
    }
}

You can call this color definition as usual from your views, e.g. errorLabel.textColor = Colors.error, the iOS system will figure out the rest for you.

You can remove the #available(iOS 13, *) line if you are not supporting iOS versions prior to iOS 13.

After defining a dynamic color, when you use it in your view or view controller, you don’t pass the trait collection. So how does the system know which color to use?

There is a new property on UITraitCollection called current. This property is set automatically by UIKit, so the developer don’t need to worry about it.

Defining colors via asset catalog

If you prefer to define your colors via an Asset Catalog, you can configure Dark Mode there directly.

Open a color in the Asset Catalog, then select Any, Dark in Appearances of Attributes Inspector and you will be presented with a new color dark mode setting.

In code, you can use these colors as usual:

var errorColor: UIColor {
    return UIColor(named: "error")
}

Images

To add dark mode support for images, it is the same process as for colors with the Asset Catalog. Select Any, Dark in Appearances of Attributes Inspector, you then will be presented with the same interface as for colors to configure dark mode images.

Good to know

Only supporting light mode

As long as you are not supporting dark mode, set Info.plist key UIUserInterfaceStyle to Light.

This way, you can avoid unwanted appearance effects when users use your app with dark mode turned on.

Overriding user interface style for certain views

If you want a certain view or view controller always to use a certain mode, you can simply do it by overwriting it’s overrideUserInterfaceStyle property.


Did you like this post? Then let me know by clicking on the like button below.

Like to stay updated? You can follow me on Twitter or subscribe to this blog. If you like to read on Medium, I’m also publishing my posts there. Feel free to contact me if you have any questions or want to give me some feedback.


Image by Randy Rodriguez from Pixabay

2+
Books I can recommend. Click on the book to open on Amazon*