In my app, there are two themes: a light theme, and a dark theme (both custom defined). They are defined in a class called LightTheme and DarkTheme, respectively, and both conform to ThemeProtocol which simply defines colors for each aspect. A class called ThemeManager handles switching/setting themes and specific colors. When the user changes from light mode to dark mode or vice versa, the settings view controller calls a method called updateColors()
to reflect the switch to dark or light mode. Everything works fine - the background color updates as do other views through the updateColors()
method. The only element in which colors fail to update is the navigation bar. This causes the items in the navigation bar to be the same color as the background.
private func updateColors() {
// other colors are changed here, works fine
// changing the color does not work; icons are still the color they were before
self.navigationController?.navigationBar.tintColor = UIColor.blue
}
This answer doesn't work for me because I am already using the answer's method of updating the navigation colors.
It is worth mentioning that I configure the navigation bar in the root view controller like this:
let backImage = NewImages.backArrow?.withRenderingMode(.alwaysOriginal).withAlignmentRectInsets(UIEdgeInsets(top: 0, left: -Padding.intermediate, bottom: 0, right: 0))
self.navigationController?.navigationBar.backIndicatorImage = backImage
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backImage
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
let settingsImage = NewImages.settings?.withRenderingMode(.alwaysOriginal).withAlignmentRectInsets(UIEdgeInsets(top: 0, left: Padding.intermediate, bottom: 0, right: 0))
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: settingsImage, style: .done, target: self, action: #selector(self.settingsButtonClicked))
self.navigationItem.rightBarButtonItem?.imageInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: Padding.intermediate)
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
The above code sets a back button and a button to go to the settings view controller. The background of the navigation bar is also set to an empty image, making the background color clear.
After an hour or two of fiddling around with different combinations of code, it turned out that it was an extremely small error. While copying and pasting code into my question, I realized the issue. I am answering my own question to help others down the road who have the same problem as me.
In my Assets.xcassets
folder, my images are set to render as template image so that I don't have to import different colored images for each theme - I can just change the tintColor
to reflect the color I want. My problem lies with these two lines (NewImages
is simply a struct with attributes of type UIImage
for each of my image assets):
let backImage = NewImages.backArrow?.withRenderingMode(.alwaysOriginal).withAlignmentRectInsets(UIEdgeInsets(top: 0, left: -Padding.intermediate, bottom: 0, right: 0))
let settingsImage = NewImages.settings?.withRenderingMode(.alwaysOriginal).withAlignmentRectInsets(UIEdgeInsets(top: 0, left: Padding.intermediate, bottom: 0, right: 0))
As you can see, the rendering mode of these images is set to .alwaysOriginal
. I changed it to .alwaysTemplate
, and the issue was solved.