Backward Compatible Dark Mode on iOS
In iOS, people can now choose to adopt a dark system-wide appearance called Dark Mode. In Dark Mode, the system uses a darker color palette for all screens, views, menus, and controls, and it uses more vibrancy to make foreground content stand out against the darker backgrounds.
At WWDC 2019, Apple announced that Dark Mode would be supported on iOS 13 and later only. There are some significant changes to UIKit in order to support this — many of them are detailed in the talk Implementing Dark Mode on iOS which I’d highly recommend watching.
Now the question is how do we configure colors for light and dark mode? Well, we can use the color asset catalog for that. Colors for Dark and Light mode can be added into the catalog.
Color Asset Catalog
The color asset catalog can only add colors for Dark and Light mode. But what if we want to add more colors for multiple themes? Imagine an app that changes the appearance based on whether it’s paid paid or free app.
What’s the solution?
A workable solution is to check whether the app is running on iOS 13, then check selected theme and set the color accordingly. This means we’ll probably be doing a lot of things like using Swift’s available syntax #available(iOS 13, *)
. But it requires a lot of repetitive code and unnecessary changes.
Also iOS 10 doesn’t support the color asset catalog. UIColor(named: “”)
is supported from iOS 11 and later only. What if the app is running on iOS 10? There must be a better way to do this, right?
A better solution would be to create our own custom UIColor
wrapper supporting colors for different themes. While making these wrappers, we have to make sure that the syntax remains the same as Apple API’s for UIColor
(e.g. calling UIColor.black
).
Let’s code
Create a struct Theme
consisting of variables for every theme supported by the app.
Our Theme propertyWrapper is ready. Now let’s list all the colors which will be used in the app. We will create an extension of UIColor
and create color variables with the Theme
attribute.
That’s it. We will set the color using the same syntax UIColor.background
and the color will be changed according the theme set.
The above implementation works fine for the devices running iOS 13 and later. What about the devices running on iOS 12 and before?
What about Older versions?
To support devices running on older versions of iOS, we will create a protocol ThemeProtocol
.
The ThemeProtocol
protocol has the default implementation of addThemeChangeObserver()
.
Now we just have to conform the ViewController
to the ThemeProtocol
and call addThemeChangeObserver
in viewDidLoad
and implement configureThemeColors
, where we will configure all our UI elements color.
That’s all. Now whenever the theme is changed, we just have to fire the ThemeDidChangeNotification
notification and the color of the UI elements will be changed accordingly, even for the devices running on iOS version 12 and below.
Conclusion
Dark Mode was one of the most anticipated feature for iOS users in 2019. It adds a darker theme to the iPhone and allows you to do the same for your apps. In this article we’ve explored how to make our app look great by implementing Dark Mode that works on all iOS versions including iOS 12 and below.
Hopefully this makes your app’s transition to dark mode easier!