Swift 改变颜色时更新 UIColor

Swift update UIColor when change color

我正在练习扩展和结构中的 UIColor 和 CGColor。一切正常,但我意识到如果将来我将添加 "Theme" 功能,如果我从红色更改为蓝色,如何在更改主题时更新所有 UIColor 和 CGColor?

例如,当我按下按钮将主题更改为蓝色时,它如何更新所有 UIColor / CGColor?

这是我的代码:

extension UIColor {
    public class func dynamicColor(light: UIColor, dark: UIColor) -> UIColor {
        return UIColor {
            switch [=11=].userInterfaceStyle {
            case .dark: return dark
            default: return light
            }
        }
    }
}

var themePick = "Red"
struct AiooColor {
    static var tableviewerHeaderTitle: UIColor {
        switch themePick {
        case "Red": return UIColor.dynamicColor(light: UIColor.systemRed, dark: UIColor.systemRed)
        case "Blue": return UIColor.dynamicColor(light: UIColor.systemBlue, dark: UIColor.systemBlue)
        // DEFAULT WILL SET TO RED
        default: return UIColor.dynamicColor(light: UIColor.systemRed, dark: UIColor.systemRed)
        }
    }

    static var tableviewerHeaderBackground: UIColor {
        switch themePick {
        case "Red": return UIColor.dynamicColor(light: UIColor(red: 255/255, green: 204/255, blue: 204/255, alpha: 1), dark: UIColor(red: 30/255, green: 0/255, blue: 0/255, alpha: 1))
        case "Blue": return UIColor.dynamicColor(light: UIColor(red: 204/255, green: 204/255, blue: 255/255, alpha: 1), dark: UIColor(red: 0/255, green: 0/255, blue: 30/255, alpha: 1))
        // DEFAULT WILL SET TO RED
        default: return UIColor.dynamicColor(light: UIColor(red: 20/255, green: 0/255, blue: 0/255, alpha: 1), dark: UIColor(red: 20/255, green: 0/255, blue: 0/255, alpha: 1))
        }
    }
}

假设您有以下结构来跟踪用户首选项键:

struct PreferenceKeys {
    static let themeStyle = "theme_style"
}

以及以下枚举(原始类型)来描述您的主题风格:

enum ThemeStyle: Int {
    case themeA = 0
    case themeB
    case themeC
    case themeD
}

首先,我将创建一个自定义服务来管理您的主题。我们称它为 ThemeService。这将允许您存储和检索用户选择的活动主题样式。它可以像这样简单:

protocol ThemeServiceInterface {
    func setThemeStyle(_ themeStyle: ThemeStyle)
    func getThemeStyle() -> ThemeStyle
}

final class ThemeService: ThemeServiceInterface {

    static let shared = ThemeService()

    let userDefaults: UserDefaults

    private init() {
        self.userDefaults = UserDefaults.standard
    }

    func setThemeStyle(_ themeStyle: ThemeStyle) {
        userDefaults.set(themeStyle.rawValue, forKey: PreferenceKeys.themeStyle)
    }

    func getThemeStyle() -> ThemeStyle {
        let rawValue = userDefaults.integer(forKey: PreferenceKeys.themeStyle)
        if let themeStyle = ThemeStyle(rawValue: rawValue) {
            return themeStyle
        }
        return .themeA
    }
}

因此,当您尝试访问特定颜色时,只需询问您的主题服务什么是活动主题样式,然后相应地设置您的颜色。

extension UIColor {

    static var primaryColor: UIColor {
        switch ThemeService.shared.getThemeStyle() {
        case .themeA: return .systemBlue
        case .themeB: return .systemRed
        case .themeC: return .systemGreen
        case .themeD: return .systemIndigo
        }
    }

    static var secondaryColor: UIColor {
        .systemPink
    }

    // ...
}

现在当你的用户想要设置一个新的主题样式时,你只需要调用下面的方法:

ThemeService.shared.setThemeStyle(.themeC)

太棒了,您所有新创建的视图都将反映新的主题样式。

但是现在到了我们需要为所有现有视图重置 UI 的部分。那么,根据项目的结构,您会有不同的选择。

例如,您可以让 ThemeService 通过 NotificationCenter 向所有屏幕发送通知,要求它们重新加载 UI(使用 setNeedsDisplay() / setNeedsLayout() 方法例如)

如果这听起来对您的项目来说工作量太大,另一种不错且简单的方法可能是用漂亮的动画简单地重置您的 UIWindow 的 rootViewController,这将导致您的 UI 被重置并匹配活动主题样式。

希望对您有所帮助!