How can I make a switch to change programatically to dark or light mode in my iOS app? I'm using Swift.
You can opt dark mode as per UIViewcontroller or UIView by setting overrideUserInterfaceStyle property to dark otherwise in Xcode 11 the by default it is dark.
On a device, you can enable Dark Mode by navigating to the Display & Brightness page in the Settings app. However, it’s a lot easier during development to add an option to the Control Centre to quickly switch between dark and light mode: While working in Xcode with the simulator open you might want to use the Environment Overrides window instead.
If you don’t have the time to add support for Dark mode you can simply disable it by adding the UIUserInterfaceStyle to your Info.plist and set it to Light. You can override the user interface style per view controller and set it to light or dark using the following code:
There are multiple ways to enable and switch appearance mode that all have their benefits. Navigate to the Developer page in the Settings app on your simulator and turn on the switch for Dark Appearance: On a device, you can enable Dark Mode by navigating to the Display & Brightness page in the Settings app.
Dark mode can be detected by using the userInterfaceStyle property on the current trait collection. When it’s set to dark you know that the current appearance is set to dark. When you use adaptive colors with CALayers you’ll notice that these colors are not updating when switching appearance live in the app.
You can override the style for single views or view controller using the overrideUserInterfaceStyle
property. But since the window is also a view, you can set that on your main window to force it into light or dark mode:
window.overrideUserInterfaceStyle = .dark
You can use one of the observation ways, for example, Defaults
lib, and then add
window.overrideUserInterfaceStyle = .dark
to
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {}
method
I want to elaborate more on the answer provided by @Frank Schlegel.
To change theme from another view controller in your app (which is what you originally asked for, I think) you could add an observer for a UserDefaults
value that will trigger the change.
I would add an enum to better represent the theme state
enum Theme: String {
case light, dark, system
// Utility var to pass directly to window.overrideUserInterfaceStyle
var uiInterfaceStyle: UIUserInterfaceStyle {
switch self {
case .light:
return .light
case .dark:
return .dark
case .system:
return .unspecified
}
}
}
In your SceneDelegate
under your window
initialisation you have to add this method that is triggered every time UserDefaults
changes value.
UserDefaults.standard.addObserver(self, forKeyPath: "theme", options: [.new], context: nil)
Also, you want to remove that observer when the SceneDelegate
is deinitialised, add
deinit {
UserDefaults.standard.removeObserver(self, forKeyPath: "theme", context: nil)
}
This will place an observer for that theme
value in UserDefaults
.
To handle changes you need to add this method to your SceneDelegate
class.
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
guard
let change = change,
object != nil,
keyPath == Defaults.theme.rawValue,
let themeValue = change[.newKey] as? String,
let theme = Theme(rawValue: themeValue)?.uiInterfaceStyle
else { return }
UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveLinear, animations: { [weak self] in
self?.window?.overrideUserInterfaceStyle = theme
}, completion: .none)
}
This will be executed every time theme
value changes in UserDefaults
and will animate the transition from a theme to another.
Now, to change your theme from other view controllers in your app you just need to change value for UserDefaults
.
UserDefaults.standard.setValue(Theme.light.rawValue, forKey: "theme")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With