Функция делегата в appDelegate не меняет цвета панели навигации - PullRequest
2 голосов
/ 16 марта 2020

Xcode 11.3.1, iOS 13

Я пытаюсь изменить цвет панели навигации на всех контроллерах вида, если в приложении существует определенное условие. Казалось логичным использовать тот же код, который изначально устанавливает глобальный цвет, используя функцию делегата в AppDelegate.

Вот мой код:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    var myColor : UIColor?

    let themeColorUS = UIColor(red: 0.991, green: 0.621, blue: 0.022, alpha: 1.00)
    let themeColorCanada = UIColor(red: 0.001, green: 0.686, blue: 0.000, alpha: 1.00)
    let themeColorGeneral = UIColor(red: 0.000, green: 0.954, blue: 0.969, alpha: 1.00)

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        UserDefaults.standard.setValue(false, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable")

        setBarColors(issuingFlag: "General")

        return true
    }

...

func setBarColors(issuingFlag:String) {

    if issuingFlag == "US" {
        myColor = themeColorUS
    }else if issuingFlag == "Canada"{
        myColor = themeColorCanada
    }else{
        myColor = .magenta
    }

    print("issuingFlag == \(issuingFlag)")

    if #available(iOS 13.0, *) {

        let appearance = UINavigationBarAppearance()
        appearance.backgroundColor = myColor
        appearance.titleTextAttributes = [.foregroundColor: UIColor.black]
        appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black]

        UINavigationBar.appearance().tintColor = .black
        UINavigationBar.appearance().standardAppearance = appearance
        UINavigationBar.appearance().compactAppearance = appearance
        UINavigationBar.appearance().scrollEdgeAppearance = appearance
    } else {
        UINavigationBar.appearance().tintColor = .black
        UINavigationBar.appearance().barTintColor = myColor
        UINavigationBar.appearance().isTranslucent = false
    }

}

В дополнение к первоначальному вызову setBarColors(), когда приложение открывается (что работает нормально), я также вызываю его из viewController в приложении, например, который ничего не делает с navBars, даже если функция получает соответствующие данные в его параметре:

    if detailFlag.issuedBy == "Canada"{
    appDelegate.setBarColors(issuingFlag: "Canada")

    }else if detailFlag.issuedBy == "US"{
    appDelegate.setBarColors(issuingFlag: "US")
    }

Может кто-нибудь помочь мне с тем, почему функция не переключает цвета navBar?

TIA!

1 Ответ

2 голосов
/ 16 марта 2020

Я бы посоветовал, поскольку вы хотите динамически изменять тему NavigationBar (например, цвет фона) на основе значения модели флага, а не go для способа AppDelegate, поскольку это сделает это один раз для вас, и это считается более глобальным способом установки стиля NavigationBar до того, как фактически будет создано любое представление.

Есть несколько способов применить это, например, через extension ViewController, inheritance with base class .., а также различные способы, которыми вы можете получить / установить значения флага для изменения цвета навигации, например, через userdefaults, variables ... Я приведу пример, чтобы вы могли начать:

import UIKit

class ViewController: BaseViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        currentFlag = "Canada"
    }
}

class BaseViewController: UIViewController {

    var currentFlag: String = "General" {
        didSet {
            setNavBarColor()
        }
    }

    private let themeColorUS = UIColor(red: 0.991, green: 0.621, blue: 0.022, alpha: 1.00)
    private let themeColorCanada = UIColor(red: 0.001, green: 0.686, blue: 0.000, alpha: 1.00)
    private let themeColorGeneral = UIColor(red: 0.000, green: 0.954, blue: 0.969, alpha: 1.00)

    override func viewDidLoad() {
        super.viewDidLoad()

        setNavBarColor()
    }

    private func setNavBarColor() {
        navigationController?.navigationBar.barTintColor = getBarColor(for: currentFlag)
    }

    private func getBarColor(for flag: String) -> UIColor {
        if flag == "US" {
            return themeColorUS
        } else if flag == "Canada" {
            return themeColorCanada
        }

        return themeColorGeneral
    }
}

И это означает, что мы удалили глобальный способ установки его стиля из AppDelegate, поэтому мой didFinishLaunchingWithOptions выглядит следующим образом:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    return true
}

Выполнение следующего кода (с установленным флагом Канада для моего ViewController) и наличием ViewController в раскадровке с root viewcontroller UINavigationController следующим образом: image

сделает приложение выглядеть так:

image


Рефакторинг для улучшения nts

Кроме того, вы можете сделать что-то еще, просто чтобы упростить управление кодом, флагами и цветами, организовать их в структуре, я выбрал в качестве примера enum, но вы можете сделать это может быть и другими способами, просто чтобы дать вам образец, вы могли бы сделать это следующим образом:

import UIKit

enum Flag {
    case us
    case canada
    case general

    static let `default` = Flag.general

    init(rawValue: String) {
        switch rawValue {
        case "US":
            self = .us
        case "Canada":
            self = .canada
        case "General":
            self = .general
        default:
            self = .default
        }
    }

    var themeColor: UIColor {
        switch self {
        case .us:
            return UIColor(red: 0.001, green: 0.686, blue: 0.000, alpha: 1.00)
        case .canada:
            return UIColor(red: 0.001, green: 0.686, blue: 0.000, alpha: 1.00)
        case .general:
            return UIColor(red: 0.000, green: 0.954, blue: 0.969, alpha: 1.00)
        }
    }
}

class ViewController: BaseViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        currentFlag = .canada
    }
}

class BaseViewController: UIViewController {

    var currentFlag: Flag = .default {
        didSet {
            setNavBarColor()
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        setNavBarColor()
    }

    private func setNavBarColor() {
        navigationController?.navigationBar.barTintColor = currentFlag.themeColor
    }
}
...