I have three view controllers embedded within a UINavigationController
. FirstViewController
navigates to SecondTableViewController
, which navigates to ThirdDetailViewController
.
The problem I am having is when customising the style of the status bar
and UINavigationBar
using the scrollViewDidScroll
method within the SecondTableViewController
it also override the other view controllers within the stack that come after it as well as all status bar styles.
Does anybody know how I can prevent the scrollViewDidScroll method from effecting other view controllers within the stack ?
FirstViewController
override func viewWillAppear(animated: Bool) {
UIApplication.sharedApplication().statusBarStyle = .Default
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarPosition: .Any, barMetrics: .Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.backgroundColor = UIColor.whiteColor()
self.navigationController?.navigationBar.tintColor = UIColor.blackColor()
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.translucent = true
}
SecondTableViewController
I change the style of the navigation depending on how far down the user has scrolled to either blend in or stand out from the content.
The style of other view controllers change to whichever style is set in the method.
override func scrollViewDidScroll(scrollView: UIScrollView) {
let color = colorWheel()
if (scrollView.contentOffset.y > -60) {
UIApplication.sharedApplication().statusBarStyle = .Default
self.navigationController?.navigationBar.setBackgroundImage(nil, forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.backgroundColor = UIColor.whiteColor()
self.navigationController?.navigationBar.tintColor = color.appColor
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
self.navigationController?.view.backgroundColor = color.appColor
self.navigationController?.navigationBar.translucent = true
} else {
UIApplication.sharedApplication().statusBarStyle = .LightContent
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: UIBarMetrics.Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.backgroundColor = UIColor.clearColor()
self.navigationController?.navigationBar.tintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.barTintColor = UIColor.clearColor()
self.navigationController?.view.backgroundColor = UIColor.clearColor()
self.navigationController?.navigationBar.translucent = true
}
}
ThirdDetailViewController
override func viewWillAppear(animated: Bool) {
UIApplication.sharedApplication().statusBarStyle = .Default
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarPosition: .Any, barMetrics: .Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.backgroundColor = UIColor.whiteColor()
self.navigationController?.navigationBar.tintColor = UIColor.blackColor()
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.translucent = true
}
This is by (UIKit framework) design.
Your hierarchy is like this:
hosting inside its stack
Any UIViewController subclass that means also your controllers inherits a property called
.navigationController.
This simply points to whichever navigation controller hosts the view controller.That means all three controllers you have point to THE SAME navigation controller. It's logical that it doesn't matter WHERE you do changes to
.navigationController
- because it's always the same and one and only navigation controller with one and only navigation bar, if you push or pop any view controller to the navigation stack, you will still see the latest styling you applied for the navigation bar.The solution for you is to handle the navigation bar styling EXPLICITLY in EACH controller.
BONUS TRACK:
You can extract the navigation bar styling into a UIViewController extension. You could have a method called
setNavigationStyle
, define an enum NavigationStyle with some style cases, implement the style for each case inside the method, and then in any view controller insideviewWillAppear
..just callsetNavigationStyle: .Dark
or whatever. This will scale nicely because you might have 3 style but 14 controllers. This way you prevent duplication of style implementation all over the place and make code reusable.Change the Navigation properties from within the
viewDidAppear
method as well.