I wasn't happy having to make each viewcontroller responsible for sending the background to the back in each its viewDidAppear methods, so I tried subclassing UINavigationBar instead. The UINavigationBar class uses the insertSubview:atIndex: method to insert new UIBarButtons etc. So each time this is called, we need to send our background to the back.
@interface MTNavigationBar : UINavigationBar
{
UIImageView *bg;
}
-(void)setBackgroundImage:(UIImage*)image;
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
@end
@implementation MTNavigationBar
-(void)setBackgroundImage:(UIImage*)image {
if(image == nil) return;
bg = [[UIImageView alloc]initWithImage:image];
bg.frame = CGRectMake(0.f, 0.f, self.frame.size.width, self.frame.size.height);
[self addSubview:bg];
[self sendSubviewToBack:bg];
[bg release];
}
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index
{
[super insertSubview:view atIndex:index];
[self sendSubviewToBack:bg];
}
@end
Now, in my XIB file, I changed the class of the Navigation Bar to MTNavigationBar.
Since the UINavigationController class is still expecting a UINavigationBar in the navigationBar property, I needed to cast it explicitly whenever setting the background. E.g.:
[((MTNavigationBar*) navigationController.navigationBar) setBackgroundImage:[UIImage imageNamed:@"Header.png"]];