Как создать инициализатор с dynamicProvider для темного режима - PullRequest
0 голосов
/ 15 октября 2019

Работая над поддержкой темного режима, я смог получить динамические цвета, которые меняются при смене темы с помощью этого шаблона:

static var dynamicColor: UIColor = {
    if #available(iOS 13, *) {
        return UIColor { (traitCollection: UITraitCollection) -> UIColor in
            switch (traitCollection.userInterfaceStyle, traitCollection.accessibilityContrast) {
            case (.dark, .high):
                return .somethingCustom4

            case (.dark, _):
                return .somethingCustom2

            case (_, .high):
                return .somethingCustom3

            default:
                return .somethingCustom1
            }
        }

    } else {
        return .somethingCustom1
    }
}()

Я пытаюсь упростить создание UIColor междуiOS 12 и 13 с поддержкой темного режима. Я придумал простое перечисление Theme для инкапсуляции всей вышеприведенной логики, и оно просто раскрывает 4 случая, поэтому приведенное выше заявление упрощается до следующего:

static var customColor: UIColor = {
    switch UIColor.theme {
    case .light:
        return somethingCustom1

    case .dark:
        return .somethingCustom2

    case .lightHighContrast:
        return somethingCustom3

    case .darkHighContrast:
        return .somethingCustom4
    }
}()

Проблема в том, что до упрощения все обновлялоськак следует, теперь theme не получает обновленное значение, поэтому цвета не меняются. Вот как я объявляю Theme с инициализатором init(dynamicProvider:), но кажется, что UITraitCollection.current не имеет правильного значения при переключении между темным / светлым режимом:

public enum Theme {
    case light, dark, lightHighContrast, darkHighContrast

    @available(iOSApplicationExtension 13.0, *)
    init(dynamicProvider: @escaping (UITraitCollection) -> Theme) {
        self = dynamicProvider(UITraitCollection.current)
    }
}

public extension UIColor {
    static var theme: Theme {
        if #available(iOS 13, *) {
            return Theme { (traitCollection: UITraitCollection) -> Theme in
                switch (traitCollection.userInterfaceStyle, traitCollection.accessibilityContrast) {
                case (.dark, .high):
                    return .darkHighContrast

                case (.dark, _):
                    return .dark

                case (_, .high):
                    return .lightHighContrast

                default:
                    return .light
                }
            }

        } else {
            return .light
        }
    }
}

Чтоя здесь не так делаю? Я думаю, что именно так должен работать этот инициализатор, но я не смог найти других примеров этого онлайн ...

1 Ответ

0 голосов
/ 15 октября 2019

Хорошо, так что после большого количества возни я все еще не уверен, почему оригинальная реализация не работает, но я нашел другой способ заставить ее работать! Поэтому, если вы пытаетесь упростить свою реализацию для поддержки iOS 12 и 13, вот что я получил в итоге:

public extension UIColor {
    private static func make(dynamicProvider: @escaping (Theme) -> UIColor) -> UIColor {
        guard #available(iOSApplicationExtension 13.0, *) else { return dynamicProvider(.light) }
        return UIColor { (traitCollection) -> UIColor in
            return dynamicProvider(Theme(traitCollection))
        }
    }

    static var customColor: UIColor {
        return .make { (theme) -> UIColor in
            switch theme {
            case .light:
                return .somethingCustom1

            case .dark:
                return .somethingCustom2

            case .lightHighContrast:
                return .somethingCustom3

            case .darkHighContrast:
                return .somethingCustom4
            }
        }
    }
}

public enum Theme {
    case light, dark, lightHighContrast, darkHighContrast

    @available(iOSApplicationExtension 13.0, *)
    init(_ traitCollection: UITraitCollection) {
        switch (traitCollection.userInterfaceStyle, traitCollection.accessibilityContrast) {
        case (.dark, .high):
            self = .darkHighContrast

        case (.dark, _):
            self = .dark

        case (_, .high):
            self = .lightHighContrast

        default:
            self = .light
        }
    }
}
...