Search code examples
objective-cipaduinavigationbarappearance

UIPopoverController Nav Bar Appearance


I am using this code to customise my nav bar image throughout my app.

UIImage *navBarTexture = [[UIImage imageNamed:@"NavBarTexture_iPad"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
    [[UINavigationBar appearance] setBackgroundImage:navBarTexture forBarMetrics:UIBarMetricsDefault];
    [[UINavigationBar appearance] setBackgroundImage:navBarTexture forBarMetrics:UIBarMetricsLandscapePhone];

This works wonders. However, when using this image on the nav bar in UIPopoverControllers, it looks a bit strange. The default Apple image for it is what I want to use, how can I make it retain that original appearance?

I know I can use appearanceWhenContainedIn: however if I return nil as an image, I just get a black space.


Solution

  • The first thing that crossed my mind is to simply get the default image from the navigation bar before customization. I was shocked that it worked.

    UINavigationBar *appearanceProxBar = [UINavigationBar appearance];
    UIImage *defaultImage = [appearanceProxBar backgroundImageForBarMetrics:UIBarMetricsDefault];
    [appearanceProxBar setBackgroundImage:navBarTexture forBarMetrics:UIBarMetricsDefault];
    [[UINavigationBar appearanceWhenContainedIn:[UIPopoverController class], nil] setBackgroundImage:defaultImage forBarMetrics:UIBarMetricsDefault];
    

    Also, as you can see in the answer, the WWDC 2012 - 216 - Advanced Appearance Customization on iOS had a neat trick of casting the appearance proxy to an instance of the appropriate class so the compiler can warn of unrecognized selectors, and also code completion is more precise.