Adding dark mode to a UIKit App Nov 4 2020
First, remember create a new branch for the changes, we can do that using Xcode or the git(1)
command-line tool.
Table of Contents
The basic support
iOS 13 introduced semantic colours, so UIKit already comes with support for automatic colour selection depending on the UserInterfaceStyle
. So the simplest setup is to change our UIColor
to semantic colours. For example:
1
2
3
4
5
if #available(iOS 13.0, *) {
view.backgroundColor = UIColor.systemBackground
} else {
view.backgroundColor = UIColor.white// Fallback on earlier versions
}
The alternative would be UIColor.secondarySystemBackground
. You can check the UI Elements Colours on the Apple Documentation.
Allowing the user to set the theme
We could define themes and allow the user to choose between them. For example (Inside a ViewController
):
1
2
3
4
5
func setDarkModeTheme() {
if #available(iOS 13.0, *) {
view.window?.overrideUserInterfaceStyle = .dark // [.dark, .light, .unspecified]
}
}
Storing the user preferences on UserDefaults
Let's assume we are using an enum
to represent the theme:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum ThemeStyle: Int {
case dark = 1
case light = 2
case systemDefault = 3
}
extension ThemeStyle {
var userInterfaceTheme: UIUserInterfaceStyle {
switch self {
case .dark:
return .dark
case .light:
return .light
case .systemDefault:
return .unspecified
}
}
}
We can get and set a theme key on the user's defaults, by saving the raw value of the theme on the UserDefaults
.
Reading from UserDefaults
:
1
2
3
4
//Read from UserDefaults
let defaults = UserDefaults.standard
let themeRaw = defaults.integer(forKey: "MyTheme")
let theme = ThemeStyle(rawValue: themeRaw) ?? ThemeStyle.systemDefault
Notice that defaults.integer(forKey:)
will return 0 if it didn't find a value for the "MyTheme" key.
Setting the value, assuming that we have the following enum
for the theme style:
We can save the style in UserDefaults
with the following code:
1
2
3
let defaults = UserDefaults.standard
self.theme = theme
defaults.set(self.theme.userInterfaceTheme.rawValue, forKey: "MyTheme")
Related topics/notes of interest
- Apple's documentation on supporting dark mode in your interface
- UI Elements Colours on the Apple Documentation