我正在尝试向我的应用添加主题(深色主题)。因此,当用户单击活动开关时,它将使整个应用进入暗模式。我对黑暗模式进行了硬编码,只是为了看看它会是什么样子。但是现在我希望能够通过和UISwitch启用和禁用它,但是我不确定该怎么做?
class DarkModeTableViewCell: UITableViewCell { var DarkisOn = Bool() let userDefaults = UserDefaults.standard @IBOutlet var darkModeSwitchOutlet: UISwitch! override func awakeFromNib() { super.awakeFromNib() } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } @IBAction func darkModeSwitched(_ sender: Any) { if darkModeSwitchOutlet.isOn == true { //enable dark mode DarkisOn = true userDefaults.set(true, forKey: "DarkDefault") userDefaults.set(false, forKey: "LightDefault") } else { //enable light mode DarkisOn = false userDefaults.set(false, forKey: "DarkDefault") userDefaults.set(true, forKey: "LightDefault") } } } class DarkModeViewController: UIViewController { func set(for viewController: UIViewController) { viewController.view.backgroundColor = UIColor(red: 0.1, green: 0.1, blue: 0.1, alpha: 1.0) viewController.navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white] viewController.navigationController?.navigationBar.tintColor = UIColor.white viewController.navigationController?.navigationBar.barStyle = UIBarStyle.black viewController.tabBarController?.tabBar.barStyle = UIBarStyle.black } static let instance = DarkModeViewController() }
然后我要做的是在每个视图控制器中调用该函数以查看其外观,但是如果开关处于打开或关闭状态,那么我必须能够访问它的bool值,然后执行该操作该功能,否则将保持不变。如果您还有其他问题,请告诉我,我知道其中有些可能没有多大意义。
更新:此问题(因此也有此答案)是在宣布iOS 13之前编写的,因此它不使用iOS 13特定的API。
我会使用通知(NSNotificationCenterAPI)解决此问题。
NSNotificationCenter
这个想法是在启用和禁用暗模式时实时通知视图控制器,以便它们也可以实时适应变化。您无需检查开关的状态或类似情况。
首先创建两个通知(您也可以只使用一个通知,并在userInfo字典中传递所需的主题,但是在这种情况下,创建两个通知会更容易,因为您需要使用Swift进行强制转换,而不能使用诸如此类)。
userInfo
NotificationsName+Extensions.swift:
NotificationsName+Extensions.swift
import Foundation extension Notification.Name { static let darkModeEnabled = Notification.Name("com.yourApp.notifications.darkModeEnabled") static let darkModeDisabled = Notification.Name("com.yourApp.notifications.darkModeDisabled") }
在所有“ themable”视图控制器上,收听以下通知:
override func viewDidLoad() { super.viewDidLoad() // Add Observers NotificationCenter.default.addObserver(self, selector: #selector(darkModeEnabled(_:)), name: .darkModeEnabled, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(darkModeDisabled(_:)), name: .darkModeDisabled, object: nil) }
不要忘记将它们删除deinit,因为将通知发送到无效对象会引发异常:
deinit
deinit { NotificationCenter.default.removeObserver(self, name: .darkModeEnabled, object: nil) NotificationCenter.default.removeObserver(self, name: .darkModeDisabled, object: nil) }
在“ themable”视图控制器中,实现darkModeEnabled(_:)和darkModeDisabled(_:):
darkModeEnabled(_:)
darkModeDisabled(_:)
@objc private func darkModeEnabled(_ notification: Notification) { // Write your dark mode code here } @objc private func darkModeDisabled(_ notification: Notification) { // Write your non-dark mode code here }
最后,切换您的开关将触发以下任一通知:
@IBAction func darkModeSwitched(_ sender: Any) { if darkModeSwitchOutlet.isOn == true { userDefaults.set(true, forKey: "darkModeEnabled") // Post the notification to let all current view controllers that the app has changed to dark mode, and they should theme themselves to reflect this change. NotificationCenter.default.post(name: .darkModeEnabled, object: nil) } else { userDefaults.set(false, forKey: "darkModeEnabled") // Post the notification to let all current view controllers that the app has changed to non-dark mode, and they should theme themselves to reflect this change. NotificationCenter.default.post(name: .darkModeDisabled, object: nil) } }
这样,当“主题”更改时,您的所有视图控制器将实时收到通知,并且它们将做出相应的反应。请注意,您需要采取措施在应用启动时显示正确的模式,但是我确定您正在这样做,因为您正在使用UserDefaults并大概检查了它们。同样值得一提的是NSNotificationCenter不是线程安全的,尽管这无关紧要,因为所有UI代码都应该放在主线程中。
有关更多信息,您可以查看NSNotificationCenter文档。
注意:此代码建立在OP的基础上。它可以简化(例如,您无需同时跟踪“亮”和“暗”状态)。