如何检查 iOS/iPadOS 中是否启用了深色模式?

How can I check whether dark mode is enabled in iOS/iPadOS?

从iOS/iPadOS13开始,可以使用深色用户界面风格,类似于macOS Mojave中引入的深色模式。如何检查用户是否启用了系统范围的黑暗模式?

您应该检查 UITraitCollectionuserInterfaceStyle 变量,与 tvOS 和 macOS 相同。

switch traitCollection.userInterfaceStyle {
case .light: //light mode
case .dark: //dark mode
case .unspecified: //the user interface style is not specified
}

您应该使用UIView/UIViewControllertraitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)功能来检测界面环境的变化(包括用户界面风格的变化)。

来自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.

系统默认UI个元素(例如UITabBarUISearchBar)自动适应新的用户界面风格。

正如 daveextreme 所提到的,当您使用 overrideUserInterfaceStyle 属性 时,检查当前视图用户界面样式并不总是 return 系统样式。在这种情况下,最好使用以下代码:

switch UIScreen.main.traitCollection.userInterfaceStyle {
case .light: //light mode
case .dark: //dark mode
case .unspecified: //the user interface style is not specified
}

检测变化的最佳点是 UIView/UIViewController.

的 traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) 函数
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
}

通过覆盖视图控制器上的 traitCollectionDidChange 来检测外观变化是微不足道的。然后,只需访问视图控制器的 traitCollection.userInterfaceStyle.

但是,重要的是要记住 traitCollectionDidChange 可能会被其他特征更改调用,例如设备旋转。您可以使用此新方法检查当前外观是否不同:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    let hasUserInterfaceStyleChanged = previousTraitCollection.hasDifferentColorAppearance(comparedTo: traitCollection) // Bool
    // Update your user interface based on the appearance
}

在 objective-c 你想做的事:

if( self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ){

        //is dark
}else{

    //is light

}

您可以使用此扩展程序:

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
        }
    }

对于iOS 13,你可以使用这个属性来检查当前风格是否为深色模式:

if #available(iOS 13.0, *) {
    if UITraitCollection.current.userInterfaceStyle == .dark {
        print("Dark mode")
    }
    else {
        print("Light mode")
    }
}

1/ 对于 UIView/UIViewController:

self.traitCollection.userInterfaceStyle == .dark

2/ 对于静态或其他:

UITraitCollection.current.userInterfaceStyle == .dark

但是:

//Never use this! You will get wrong value in app extensions (ex. ToDay widget)
UIScreen.main.traitCollection.userInterfaceStyle == .dark //WRONG!

Objective C

要检测何时通过控制中心启用或禁用深色模式,请使用 "appDidBecomeActive" 通知,当您 return 使用您的应用程序时将触发该通知。

//----------------------------------------------------------------------------
//                          viewWillAppear
//----------------------------------------------------------------------------
- (void)viewWillAppear {
    [super viewWillAppear];

    [[NSNotificationCenter defaultCenter]addObserver:self
                                   selector:@selector(appDidBecomeActive:)
                                   name:UIApplicationDidBecomeActiveNotification
                                   object:nil];

}

完成后别忘了将其删除:

//------------------------------------------------------------------------------------
//                    viewWillDisappear
//------------------------------------------------------------------------------------
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    [[NSNotificationCenter defaultCenter] removeObserver:self        
                                 name:UIApplicationDidBecomeActiveNotification 
                                 object:nil];

}

当黑暗模式改变时做你需要做的事:

//----------------------------------------------------------------------------
//                          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
    }
}

为 write 方法创建一个 class 函数 1 次并随处使用

func isDarkMode() -> Bool{
    if #available(iOS 12.0, *) {
        if UIScreen.main.traitCollection.userInterfaceStyle == .dark {
            return true
        } else {
            return false
        }
    } else {
       return false
    }
}  

对于Swift:

if #available(iOS 12.0, *) {
  switch UIScreen.main.traitCollection.userInterfaceStyle {
    case .dark: // put your dark mode code here
    case .light: 
    case .unspecified: 
  }
}

对于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;
        }
}

有关更多信息,请观看此 WWDC2019 video

也许是一些不错的扩展?

public extension UIViewController {
    @available(iOS 12.0, *)
    public var isDarkMode: Bool { traitCollection.userInterfaceStyle == .dark }
}

以下适用于任何 iOS 版本的辅助方法:

var isDarkMode: Bool {
    guard #available(iOS 12.0, *) else {
        return false
    }

    return UIScreen.main.traitCollection.userInterfaceStyle == .dark
}

用法:

view.backgroundColor = isDarkMode ? .black : .white

您可以使用此方法轻松检测暗模式或亮模式Swift 5

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if traitCollection.userInterfaceStyle == .light {
    print("Light mode")
} else {
    print("Dark mode")
}}

SwiftUI

使用 Environment 变量的 \.colorScheme 键:

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        Text(colorScheme == .dark ? "In dark mode" : "In light mode")
    }
}

此外,它会根据环境配色方案的变化自动更新。


UIKit

检查当前,所有符合UITraitEnvironment协议的对象,包括所有UIView子类和所有UIViewConttroller子类都可以访问当前样式:

myUIView.traitCollection.userInterfaceStyle == .dark
myUIViewController.traitCollection.userInterfaceStyle == .dark

要检测样式的实时变化,

您可以使用以下代码检查项目中的浅色或深色模式:

func viewDidLoad() {
    super.viewDidLoad()

    switch traitCollection.userInterfaceStyle {
        case .light, .unspecified:
            // light mode detected
        case .dark:
            // dark mode detected
    }
}

您还可以查看界面风格的变化:

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
}

就像自 Mojave 以来的 macOS 中一样,您可以在资产目录中为明暗模式定义图像,以便自动使用这些图像:

var isDarkMode: Bool {
    guard #available(iOS 12.0, *) else {
        return false
    }
    let window = (UIApplication.shared.delegate as? AppDelegate)?.window
    return window?.traitCollection.userInterfaceStyle == .dark
}

如果您没有在 AppDelegate 中使用 window,请从 SceneDelegate

调用 window

它与上面的大多数答案相似,但是当我们使用

更改模式时,这会更好
window?.overrideUserInterfaceStyle = .dark

可以称为

isDarkMode ? .black : .white

SwiftUI 可以非常简单地检测暗模式何时启用。我们只需添加一个 @Enviroment 变量并使用 .colorScheme 属性 扫描我们设备上的设置并查看是否启用了暗模式。

让我们看看下面的代码。

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        ZStack {
            Color(colorScheme == .light ? .blue : .red)
            Text("Hello, World!")
        }
    }
}

在上面的代码中,我们创建了@Environment 变量来查看我们的设备是否处于黑暗模式。然后在我们的 body 视图中,如果它处于黑暗模式,我们将背景颜色设置为红色,如果它不处于黑暗模式,则通过使用三元运算符内部的 colorScheme 变量将背景颜色设置为蓝色。

一个很好的用例是当用户设备处于暗模式时,如果你想支持不同的自定义UI。

快乐编码;