appDelegate 中的委托功能不会更改导航栏颜色

Posted

技术标签:

【中文标题】appDelegate 中的委托功能不会更改导航栏颜色【英文标题】:Delegate function in appDelegate doesn't change navbar colors 【发布时间】:2020-03-16 06:16:31 【问题描述】:

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 调用它,这对导航栏没有任何作用,即使该函数正在接收适当的参数中的数据:

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

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

有人可以帮我解释一下为什么该函数没有切换navBar 颜色吗?

TIA!

【问题讨论】:

【参考方案1】:

我建议,因为您想根据 Flag 模型值动态更改 NavigationBar 主题(如背景颜色),所以不要采用 AppDelegate 方式,因为这将为您完成一次,并且被认为更多的是在实际创建任何视图之前设置 NavigationBar 样式的全局方法。

您可以通过几种方式应用它,例如通过extension ViewControllerinheritance with base class.. 以及您可以获取/设置标志值以更改导航颜色的不同方式,例如通过userdefaults、@ 987654326@... 我会举一个例子来帮助你:

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 的标志设置为 Canada),并在 Storyboard 中使用 ViewController 和 UINavigationController 的根视图控制器,如下所示:

会让应用看起来像:

重构改进

您还可以做一些事情,只是为了更容易管理代码、标志和颜色,将它们组织在一个结构中,我选择了一个枚举作为示例,但您也可以用其他方式来做,只是给你一个样本,你可以这样做:

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
    

【讨论】:

非常感谢您的周到和详细的回答!由于所有冠状病毒的疯狂,我还没有实施它。很快就会这样做,并让您知道结果如何。再次感谢! 不客气,如果这对您有用,请不要忘记将其标记为正确,否则请告诉我,我自己构建它是为了让您一步一步轻松地完成 kt。保持安全! 昨晚刚开始整理,但一旦你明白我需要对我的 VC 进行子类化,我就看到了一些好事发生。那时已经是凌晨 3:00。这是我第一次使用枚举,所以很高兴你向我展示了它。我今天会做更多的工作。感谢您的检查! @rattletrap99 确定!只要确保将其标记为正确,如果这对您也有效,以便其他人在将来检查答案时受益 我在这里碰壁了。如果你有时间,你能回答几个问题吗?

以上是关于appDelegate 中的委托功能不会更改导航栏颜色的主要内容,如果未能解决你的问题,请参考以下文章

在 AppDelegate 中设置 UIButton 外观时如何更改 SafariViewController 中导航栏的色调

仅在一个 ViewController 中更改导航栏属性

如何更改应用程序委托类?

所有 UI 导航栏标题的大写字符串

转到下一个视图会更改导航栏背景颜色

SwiftUI LandScape 导航顶栏不会隐藏