UINavigationBar.appearance().tintColor does not work in Swift

I ported a file from Objective_c to Swift that among its configurations changed the tabbar color: the code I used in objective-c was:

UIColor* barColor=[UIColor colorWithRed:.88 green:.05 blue:.05 alpha:1];
if([self.navigationController.navigationBar respondsToSelector:@selector(barTintColor)])
{
    /
    self.navigationController.navigationBar.barTintColor = barColor;
}
else
{
    [[UINavigationBar appearance] setTintColor:barColor];
    /
    /
}
[super viewWillAppear:animated];


and the corresponding Swift code is:

let barColor = UIColor(red:0.88, green:0.05, blue:0.05, alpha:1)
if UIDevice.currentDevice().systemVersion.compare("8.0", options: .NumericSearch) == .OrderedDescending
    {
        /
     UINavigationBar.appearance().tintColor=barColor
     /
    }
    else
    {
        self.navigationController!.navigationBar.barTintColor = barColor;
    }

Yet, while the objective-c code did change the tab-bar color, the corresponding swift code leaves it unscathed, at least on the simulator.


What is even more puzzling is that I have a sister ViewController in which I use:

self.navigationController!.navigationBar.barTintColor = barColor

even on iOS 9 without any crash altogether and its execution actually changes the color of the tabbar.

If I use that piece of code in the original viewcontroller on iOS 9 I have a crash instead, and the alternative code has no effect.

Your Swift code is not corresponding to your Objective-C code. If you want them match, you can write something like this:

        if self.navigationController!.navigationBar.respondsToSelector("barTintColor") {
            self.navigationController!.navigationBar.barTintColor = barColor
        } else {
            UINavigationBar.appearance().tintColor=barColor
        }

Your version checking code `UIDevice.currentDevice().systemVersion.compare("8.0", options: .NumericSearch) == .OrderedDescending` returns true when systemVersion > 8.0, which may not be what you want. So, in iOS 9 the line `UINavigationBar.appearance().tintColor=barColor` is executed, which may very probably the cause of the crash.

In Swift 2, you use `#available` for version checking, but as far as I can find in the documentations, you have no need for availability checking to use `barTintColor`.

Swift is only available for targets iOS 7 or later, and the property barTintColor got available in iOS 7.


So, remove the whole if-else and replace it with:

        self.navigationController!.navigationBar.barTintColor = barColor

You say this code works in the sister ViewController, I believe the same code works in other ViewControllers.

I first tried it but it did not work: I do not remember if it crashed or always returned the same value. I shall test again and let you know when I am back at my mac.The problem about:

self.navigationController!.navigationBar.barTintColor = barColor

is that it crashed the app on iOS 9, on that specific viewController. As I said it works fine on another. I will also try this again and let you know,

It will crash if your view controller is not in UINavigationController's navigation stack. Then navigationController property is nil and accessing implicitly unwrapped optional crashes the app.

Thanks, jsslai. I should have noticed the possibility.


So, it seems I need to make one thing clear:

[[UINavigationBar appearance] setTintColor:barColor]; does not work in Objective-C neither, since iOS 7.

In fact the navigation controller was nil, if I put the conditional instead of the forced unwrapping I have no crash. Yet I do not undersand why the navigation controller is nil. I execute che code in the ViewWillAppear, is it too early to get an handle to the navigationController? The corresponding scene is the first scene of a tabBarController itself reachable from a scene which is the root scene of a custom navigation controller.

Is your view controller's parent a navigation controller? If yes the view controller's navigationController property should be set when viewWillAppear is called.

Grandfather. As a matter of fact since a few tests the navigationcontroller was found and the color correctly assigned. I think this is a bug in the simulator or iOS 9 by which at viewWillAppear time the navigation controller accessibility is shaky. At any rate by setting a conditional instead of a forced unwrapping I may avert the crash and at worst have a navigation bar of the wrong color. Finally I confim:

self.navigationController?.navigationBar.barTintColor = barColor

works even on iOS 9, as you suggested.

UINavigationBar.appearance().tintColor does not work in Swift
 
 
Q