如何以编程方式切换到暗模式 swift
How to switch programmatically to dark mode swift
如何在我的 iOS 应用程序中切换为以编程方式更改为深色或浅色模式?
我正在使用 Swift.
您可以使用 overrideUserInterfaceStyle
属性 覆盖单个视图或视图控制器的样式。但是由于 window 也是一个视图,您可以在主 window 上设置它以强制它进入亮或暗模式:
window.overrideUserInterfaceStyle = .dark
您可以使用其中一种观察方式,例如Defaults
lib,然后添加
window.overrideUserInterfaceStyle = .dark
至
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {}
方法
我想详细说明@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
}
}
}
在 SceneDelegate
的 window
初始化中,您必须添加每次 UserDefaults
更改值时触发的方法。
UserDefaults.standard.addObserver(self, forKeyPath: "theme", options: [.new], context: nil)
此外,你想在 SceneDelegate
被取消初始化时删除那个观察者,添加
deinit {
UserDefaults.standard.removeObserver(self, forKeyPath: "theme", context: nil)
}
这将在 UserDefaults
中为该 theme
值放置一个观察者。
要处理更改,您需要将此方法添加到您的 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)
}
每当 theme
值在 UserDefaults
中发生变化时都会执行此操作,并将动画从一个主题过渡到另一个主题。
现在,要从应用中的其他视图控制器更改主题,您只需更改 UserDefaults
的值。
UserDefaults.standard.setValue(Theme.light.rawValue, forKey: "theme")
如何在我的 iOS 应用程序中切换为以编程方式更改为深色或浅色模式? 我正在使用 Swift.
您可以使用 overrideUserInterfaceStyle
属性 覆盖单个视图或视图控制器的样式。但是由于 window 也是一个视图,您可以在主 window 上设置它以强制它进入亮或暗模式:
window.overrideUserInterfaceStyle = .dark
您可以使用其中一种观察方式,例如Defaults
lib,然后添加
window.overrideUserInterfaceStyle = .dark
至
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {}
方法
我想详细说明@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
}
}
}
在 SceneDelegate
的 window
初始化中,您必须添加每次 UserDefaults
更改值时触发的方法。
UserDefaults.standard.addObserver(self, forKeyPath: "theme", options: [.new], context: nil)
此外,你想在 SceneDelegate
被取消初始化时删除那个观察者,添加
deinit {
UserDefaults.standard.removeObserver(self, forKeyPath: "theme", context: nil)
}
这将在 UserDefaults
中为该 theme
值放置一个观察者。
要处理更改,您需要将此方法添加到您的 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)
}
每当 theme
值在 UserDefaults
中发生变化时都会执行此操作,并将动画从一个主题过渡到另一个主题。
现在,要从应用中的其他视图控制器更改主题,您只需更改 UserDefaults
的值。
UserDefaults.standard.setValue(Theme.light.rawValue, forKey: "theme")