How can I check whether dark mode is enabled in iOS/iPadOS?
IosIos13IpadosIos DarkmodeIos Problem Overview
Starting from iOS/iPadOS 13, a dark user interface style is available, similar to the dark mode introduced in macOS Mojave. How can I check whether the user has enabled the system-wide dark mode?
Ios Solutions
Solution 1 - Ios
For iOS 13, you can use this property to check if current style is dark mode or not:
if #available(iOS 13.0, *) {
if UITraitCollection.current.userInterfaceStyle == .dark {
print("Dark mode")
}
else {
print("Light mode")
}
}
Solution 2 - Ios
You should check the userInterfaceStyle
variable of UITraitCollection
, same as on tvOS and macOS.
switch traitCollection.userInterfaceStyle {
case .light: //light mode
case .dark: //dark mode
case .unspecified: //the user interface style is not specified
}
You should use the traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
function of UIView
/UIViewController
to detect changes in the interface environment (including changes in the user interface style).
From Apple Developer Documentation:
> The system calls this method when the iOS interface environment changes. Implement this method in view controllers and views, according to your app’s needs, to respond to such changes. For example, you might adjust the layout of the subviews of a view controller when an iPhone is rotated from portrait to landscape orientation. The default implementation of this method is empty.
System default UI elements (such as UITabBar
or UISearchBar
) automatically adapt to the new user interface style.
Solution 3 - Ios
As mentioned by daveextreme, checking the current view user interface style doesn't always return the system style when you use the overrideUserInterfaceStyle
property. In such cases it may be better to use the following code:
switch UIScreen.main.traitCollection.userInterfaceStyle {
case .light: //light mode
case .dark: //dark mode
case .unspecified: //the user interface style is not specified
}
Solution 4 - Ios
in objective-c you'd want to do:
if( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){
//is dark
}else{
//is light
}
Solution 5 - Ios
For Swift:
if #available(iOS 12.0, *) {
switch UIScreen.main.traitCollection.userInterfaceStyle {
case .dark: // put your dark mode code here
case .light:
case .unspecified:
}
}
For Objective C:
if (@available(iOS 12.0, *)) {
switch (UIScreen.mainScreen.traitCollection.userInterfaceStyle) {
case UIUserInterfaceStyleDark:
// put your dark mode code here
break;
case UIUserInterfaceStyleLight:
case UIUserInterfaceStyleUnspecified:
break;
default:
break;
}
}
For more information watch this WWDC2019 video
Solution 6 - Ios
1/ for UIView/UIViewController:
self.traitCollection.userInterfaceStyle == .dark
2/ for static or other:
UITraitCollection.current.userInterfaceStyle == .dark
BUT:
//Never use this! You will get wrong value in app extensions (ex. ToDay widget)
UIScreen.main.traitCollection.userInterfaceStyle == .dark //WRONG!
Solution 7 - Ios
SwiftUI
With the \.colorScheme
key of an Environment
variable:
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
Text(colorScheme == .dark ? "In dark mode" : "In light mode")
}
}
Also, it automatically updates on the change of the environment color scheme.
UIKit
To check the current, all object those conform to UITraitEnvironment
protocol, including all UIView
subclasses and all UIViewConttroller
subclasses have access to the current style:
myUIView.traitCollection.userInterfaceStyle == .dark
myUIViewController.traitCollection.userInterfaceStyle == .dark
To detect live changes of the style, here is the full detailed answer
Solution 8 - Ios
Create a class function for write method 1 time and use everywhere you want
func isDarkMode() -> Bool{
if #available(iOS 12.0, *) {
if UIScreen.main.traitCollection.userInterfaceStyle == .dark {
return true
} else {
return false
}
} else {
return false
}
}
Solution 9 - Ios
Objective C
To detect when dark mode is enabled or disabled via the Control Centre use an "appDidBecomeActive" notification that will be triggered when you return to your app.
//----------------------------------------------------------------------------
// viewWillAppear
//----------------------------------------------------------------------------
- (void)viewWillAppear {
[super viewWillAppear];
[[NSNotificationCenter defaultCenter]addObserver:self
selector:@selector(appDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
Don't forget to remove it when you're finished:
//------------------------------------------------------------------------------------
// viewWillDisappear
//------------------------------------------------------------------------------------
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:nil];
}
Do what ever you need to when dark mode changes:
//----------------------------------------------------------------------------
// appDidBecomeActive
//----------------------------------------------------------------------------
-(void)appDidBecomeActive:(NSNotification*)note {
if (@available(iOS 13.0, *)) {
if( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){
//dark mode
}
else {
//not dark mode
}
}
else {
//fall back for older versions
}
}
Solution 10 - Ios
Helper method below that works on any iOS version:
var isDarkMode: Bool {
guard #available(iOS 12.0, *) else {
return false
}
return UIScreen.main.traitCollection.userInterfaceStyle == .dark
}
Usage:
view.backgroundColor = isDarkMode ? .black : .white
Solution 11 - Ios
The best point to detect changes is traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) function of UIView/UIViewController.
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
let userInterfaceStyle = traitCollection.userInterfaceStyle // Either .unspecified, .light, or .dark
// Update your user interface based on the appearance
}
Detecting appearance changes is trivial by overriding traitCollectionDidChange on view controllers. Then, just access the view controller’s traitCollection.userInterfaceStyle.
However, it is important to remember that traitCollectionDidChange may be called for other trait changes, such as the device rotating. You can check if the current appearance is different using this new method:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
let hasUserInterfaceStyleChanged = previousTraitCollection.hasDifferentColorAppearance(comparedTo: traitCollection) // Bool
// Update your user interface based on the appearance
}
Solution 12 - Ios
var isDarkMode: Bool {
guard #available(iOS 12.0, *) else {
return false
}
let window = (UIApplication.shared.delegate as? AppDelegate)?.window
return window?.traitCollection.userInterfaceStyle == .dark
}
if you are not using window in AppDelegate, call window from SceneDelegate
It is similar to most answers above, but this works better when we are changing modes using
window?.overrideUserInterfaceStyle = .dark
can be called as
isDarkMode ? .black : .white
Solution 13 - Ios
You can use this extension:
import UIKit
extension UIApplication {
@available(iOS 13.0, *)
var userInterfaceStyle: UIUserInterfaceStyle? {
return self.keyWindow?.traitCollection.userInterfaceStyle
}
}
@available(iOS 13.0, *)
func setSystemTheme() {
switch UIApplication.shared.userInterfaceStyle {
case .dark?:
currentTheme = .dark
case .light?:
currentTheme = .light
default:
break
}
}
Solution 14 - Ios
Some nice extension maybe ?
public extension UIViewController {
@available(iOS 12.0, *)
public var isDarkMode: Bool { traitCollection.userInterfaceStyle == .dark }
}
Solution 15 - Ios
You can Easily Detect Dark Mode or Light Mode with this Method Swift 5
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if traitCollection.userInterfaceStyle == .light {
print("Light mode")
} else {
print("Dark mode")
}}
Solution 16 - Ios
You can use the following code to check for light, or dark mode in your project:
func viewDidLoad() {
super.viewDidLoad()
switch traitCollection.userInterfaceStyle {
case .light, .unspecified:
// light mode detected
case .dark:
// dark mode detected
}
}
You can also check for changes in the interface style:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
let userInterfaceStyle = traitCollection.userInterfaceStyle // Either .unspecified, .light, or .dark
// Update your user interface based on the appearance
}
Just like in macOS since Mojave, you can define images for both light and dark mode in your asset catalog so that those images will be used automatically:
Solution 17 - Ios
SwiftUI makes it really simply to detect when dark mode is enabled. We simply have to add a @Enviroment variable and use .colorScheme property to scan the settings on our device and see if dark mode is enabled.
Let's take a look at the code below.
struct ContentView: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
ZStack {
Color(colorScheme == .light ? .blue : .red)
Text("Hello, World!")
}
}
}
In the code above we are creating the @Environment variable to see if our device is in dark mode. Then inside of our body view we are setting the background color to red if its in dark mode or blue if its not in dark mode by using our colorScheme variable inside of a ternary operator.
A great use case for this is if you want to support different custom UI's for when the users device is in dark mode.
Happy Coding ;