Embrace the Dark Mode

Most developers already installed Xcode 11 and worked through various issues that recent iOS SDK brings to our projects. If you haven’t done it yet and want to know what to expect or you are looking for a quick solution to your problem, we’ve got you covered with a few simple tips and advice.
With iOS 13 came few notable changes on how our applications are displayed on devices. Firstly, there are changes in default presentation style of modals, about which we wrote in a separate article. Secondly, Dark Mode, which I will cover in the next few paragraphs.
What is Dark Mode?
Let’s say that Dark Mode is a switch that changes displayed colors, that is gaining more and more popularity showing up on different platforms, from Slack, Instagram or Chrome to iOS 13. It comes with various names such as light-on-dark color scheme or night mode and really, each one describe what it does. It’s main function is to replace white and black colors with each other, eg. transforming white page with black text into black page with black text. This is the most basic example, but also most noticeable. If we think about the benefits of such change, there are two most impactful. First is that OLED and LCD displays will consume way less energy while displaying bright texts on dark backgrounds, second is a common belief that reading in dark mode causes less eye strain.
So how does it work with applications on iOS 13?
Impact of Dark Mode on our applications will vary depending on our design choices. Remember all those Labels and ViewControllers backgrounds without assigned custom color, because default black and white suits our project? They use system colors that will change when user enables Dark Mode, which can cause our layout to be unreadable.
System colors like red, green or purple only slightly differ in shade or brightness when Dark Mode is turned on, while default blacks and whites (like Labels and ViewController's view) and all grays will be swapped completely, which is best illustrated in the picture below.

How to fix our applications?
There are mainly two ways to tackle most issues related to Dark Mode.
First one is a quick fix for when you want your application to just look the same as before. To do so, we will lock application in Light Mode, ignoring user’s device settings. This is possible by going to projects info.plist and adding UIUserInterfaceStyle key with value Light. That’s it.
Obviously, the second path is adding support for the Dark Mode. This will require more work, but depending on the content of our application, eg. longer paragraphs, can be highly beneficial for users.
Supporting different colors for Light and Dark Modes
Even though ability to define colors in asset catalog was introduced in Xcode 9, a lot of developers still don’t use it and create colors as UIColor extension in code.
Let's say we have such green color for our labels:
static var labelGreen: UIColor {
return UIColor(red: 25, green: 130, blue: 40, alpha: 1)
}
Unfortunately there isn’t clean and easy way to add Dark Mode variation custom color defined such way. It’s possible to check device settings and return different UIColor values based on that, it gets the job done, but also introduces a lot of repeated code.
static var labelGreen: UIColor {
if #available(iOS 13, *) {
return UIColor { (traitCollection: UITraitCollection) -> UIColor in
if traitCollection.userInterfaceStyle == .dark {
return UIColor(red: 20, green: 160, blue: 30, alpha: 1)
} else {
return UIColor(red: 25, green: 130, blue: 40, alpha: 1)
}
}
} else {
return UIColor(red: 25, green: 130, blue: 40, alpha: 1)
}
}
Depending on the designs of our application, we would need to change only a few or most of the custom UIColors, which can lead to big unreadable file.
Alternatively we have mentioned asset catalog, if we are using it in our projects, we have an easy way to support Dark Mode, and if we don’t I think this is the right time to spend some time and make a transition.
Let’s start with adding new color set for our labelGreen. To do so we proceed similar as when adding new image asset.

We can change name and configure it’s value by either using floating point (0.0 - 1.0), 8-bit (0 - 255) or hex code to define our color.

With appearances option we can add new color variations for different interface styles, we can have up to 6 colors variations for following configurations: Any, Light, Dark in both normal and high contrast option. For this example we will setup only 4 values.

And now if we want to use this color we simply initialize UIColor with name labelGreen, without any additional iOS version or interface style checks.
label.textColor = UIColor(named: "labelGreen")
Dark Mode beyond UIColor
Until now we only touched supporting Dark Mode on level of individual colors, but there are a few more features that we can make use of.
First one is similar to locking whole application in one interface style, but instead we’ll do it on UIViewController level. This allows us to configure each screen of our application separately, which helps when we have only a few screens, where we need more control over how they are being displayed. This can be done by overriding user's interface style in viewDidLoad.
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 13.0, *) {
overrideUserInterfaceStyle = .dark
}
}
So, we have our custom colors supporting Dark Mode and important screens locked in correct interface style. However, there’s still one more area that we need to check - our images in asset catalog. Fortunately, we already know how to use appearances setting, so we just need to go over all items and provide updated icons where needed.

Conclusion
Although Apple doesn’t force Dark Mode support in their guidelines, I think it is a good idea to plan adding it to our applications, especially those in active development. As you have seen it’s not that much work to do, yet we can add a lot of value for our users.
Photo by Alex on Unsplash