如何在 swift 5 中以编程方式更改应用程序主题 (Light/Dark)

How to change app theme (Light/Dark) programmatically in swift 5

我有一个最多有 10 个屏幕的应用程序,在设置屏幕中,我有一个开关可以在 dark/light 模式之间切换。我想在那个开关上更改完整的应用主题。

目前,当我在 iOS 默认设置中更改主题时,应用程序主题会发生变化。但我希望只对我的应用程序发生相同的行为。

到目前为止,我想出的是在用户默认设置中设置一个主题变量,并在每个视图控制器上有条件地使用此代码

    view.overrideUserInterfaceStyle = // .dark // .light

我不想使用任何第三方库。

在您的应用委托中 didFinishLaunchingWithOptions 从共享默认值中读取首选项并执行如下操作:

UIApplication.shared.keyWindow.overrideUserInterfaceStyle = preference == "dark" ? .dark : .light

在您的设置视图控制器中,当用户更改首选项时执行相同的操作。

在 window 上设置覆盖应该会处理所有视图控制器。

以下是我对类似用例采用相同方法的方法。我为 AppDelegate 创建了一个扩展,如下所示:

extension AppDelegate {
    func overrideApplicationThemeStyle() {
        if #available(iOS 13.0, *) {
            ....
            // Retrieve your NSUserDefaults value here
            ....
            UIApplication.shared.keyWindow?.overrideUserInterfaceStyle = yourUserDefaultsValue ? .dark : .light
        } else {
            // Fallback on earlier versions
        }
    }
}

而且,我的主题更改是针对特定设备的。因此,我在 NSUserDefaults 中创建了一个布尔实例以保持切换更改。而且,每当切换发生变化时,我都会调用方法:

@IBAction func changeApplicationTheme() {
    ....
    // Your code to store the changes in NSUserDefaults
    ....
    AppDelegate.shared.overrideApplicationStyle()
}

而且,更重要的是,这个主题是从 iOS 13 开始引入的,无论何时启动应用程序并希望应用用户选择的主题,从 func sceneDidBecomeActive(_ scene: UIScene) 调用它的最佳位置。

func sceneDidBecomeActive(_ scene: UIScene) {
    AppDelegate.shared.overrideApplicationStyle()
}