小编典典

向iOS应用添加暗模式

swift

我正在尝试向我的应用添加主题(深色主题)。因此,当用户单击活动开关时,它将使整个应用进入暗模式。我对黑暗模式进行了硬编码,只是为了看看它会是什么样子。但是现在我希望能够通过和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值,然后执行该操作该功能,否则将保持不变。如果您还有其他问题,请告诉我,我知道其中有些可能没有多大意义。


阅读 234

收藏
2020-07-07

共1个答案

小编典典

更新:此问题(因此也有此答案)是在宣布iOS 13之前编写的,因此它不使用iOS 13特定的API。


我会使用通知(NSNotificationCenterAPI)解决此问题。

这个想法是在启用和禁用暗模式时实时通知视图控制器,以便它们也可以实时适应变化。您无需检查开关的状态或类似情况。

首先创建两个通知(您也可以只使用一个通知,并在userInfo字典中传递所需的主题,但是在这种情况下,创建两个通知会更容易,因为您需要使用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 {
    NotificationCenter.default.removeObserver(self, name: .darkModeEnabled, object: nil)
    NotificationCenter.default.removeObserver(self, name: .darkModeDisabled, object: nil)
}

在“ themable”视图控制器中,实现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的基础上。它可以简化(例如,您无需同时跟踪“亮”和“暗”状态)。

2020-07-07