如何以编程方式快速切换到暗模式

The*_*988 16 xcode ios swift ios-darkmode

如何在我的 iOS 应用程序中切换到以编程方式更改为暗模式或亮模式?我正在使用斯威夫特。

Fra*_*gel 32

您可以使用该overrideUserInterfaceStyle属性覆盖单个视图或视图控制器的样式。但由于窗口也是一个视图,您可以在主窗口上设置它以强制其进入亮或暗模式:

window.overrideUserInterfaceStyle = .dark
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考:如果视图控制器添加到导航控制器中,则后者必须设置此属性。`dummyNavigation.overrideUserInterfaceStyle = .light/.dark` (3认同)
  • 要覆盖整个应用程序,您应该能够使用 UIWindow().overrideUserInterfaceStyle = UIUserInterfaceStyle.light (2认同)
  • @JorgeZapata 只是为了澄清,这不会做任何事情。(它将覆盖应用于未使用的 UIWindow 实例。)调用者应从当前场景获取窗口(如果可用),当前场景通常但并不总是 UIApplication 的连接场景中的第一个场景。干杯。 (2认同)

Mat*_*tti 7

我想详细阐述@Frank Schlegel 提供的答案。

要从应用程序中的另一个视图控制器更改主题(我认为这是您最初要求的),您可以添加一个观察者来获取UserDefaults将触发更改的值。

我会添加一个枚举以更好地表示主题状态

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在初始化SceneDelegate过程中window,您必须添加此方法,每次UserDefaults更改值时都会触发该方法。

UserDefaults.standard.addObserver(self, forKeyPath: "theme", options: [.new], context: nil)
Run Code Online (Sandbox Code Playgroud)

另外,您想在SceneDelegate取消初始化时删除该观察者,请添加

deinit {
    UserDefaults.standard.removeObserver(self, forKeyPath: "theme", context: nil)
}
Run Code Online (Sandbox Code Playgroud)

theme这将在 中放置该值的观察者UserDefaults

要处理更改,您需要将此方法添加到您的SceneDelegate类中。

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)
}
Run Code Online (Sandbox Code Playgroud)

每次theme值发生变化时都会执行此操作UserDefaults,并以动画方式从一个主题过渡到另一个主题。

现在,要从应用程序中的其他视图控制器更改主题,您只需更改 的值UserDefaults

UserDefaults.standard.setValue(Theme.light.rawValue, forKey: "theme")
Run Code Online (Sandbox Code Playgroud)

  • 如果项目不使用 `SceneDelegate` 文件怎么办? (5认同)