+2  A: 

The short answer is that modifying the structure of the UINavigationBar is not supported by Apple. They really do not want you do be doing what you are trying to do. That is what is causing the issue you are seeing.

Please file a radar requesting this feature so that it can get enough attention to be officially added at some point.

Having said that, to solve the issue you can add a category to UINavigationBar with a -drawRect: method and draw the background image in that method. Something like this will work:

- (void)drawRect:(CGRect)rect
{
  static UIImage *image;
  if (!image) {
    image = [UIImage imageNamed: @"HeaderBackground.png"];
    if (!image) image = [UIImage imageNamed:@"DefaultHeader.png"];
  }
  if (!image) return;
  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextDrawImage(context, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), image.CGImage);
}
Marcus S. Zarra
+4  A: 

After an annoying night, I found a slight tweak to this, if you use drawLayer. With drawRect, when you play a video, or youtube video, the navbar is replaced with the image. And I read a few posts that this caused their app to be rejected.

@implementation UINavigationBar (UINavigationBarCategory)

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx 
{
   if([self isMemberOfClass:[UINavigationBar class]])
   {
     UIImage *image = [UIImage imageNamed:@"navBarBackground.png"];
     CGContextClip(ctx);
     CGContextTranslateCTM(ctx, 0, image.size.height);
     CGContextScaleCTM(ctx, 1.0, -1.0);
     CGContextDrawImage(ctx,
     CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), image.CGImage); 
   }
   else 
   {        
     [super drawLayer:layer inContext:ctx];     
   }
}  
@end

If this article is accurate, all should be fine with this approach: http://developer.apple.com/iphone/library/qa/qa2009/qa1637.html

ljonesATL
Thanks! You saved my life.
Saurabh