Customize UINavigationBar buttons with image

Question: While I am developing an application for iOS 3.2 (iPad) and iOS 4 (iPhone) targets, I have to customize the navigation bar. We know that the default behavior of the navigation controller is to provide a back button with the title of the previous view controller in the queue. In my project I have to change the default look of the back button with a custom view and I have to add a home button on the right, that takes the user to the first page’s view controller by calling popViewController. The right button works and looks fine but I cannot change the back button’s image. What’s wrong? My code:
    // Hide original back button
     self.navigationItem.hidesBackButton = YES;
    // Add Left Button to act as Back Button  
    UIBarButtonItem *backButton = [[[UIBarButtonItem alloc]  
                            initWithImage:[UIImage imageNamed:@"back-button.png"]  
                            style:UIBarButtonItemStylePlain  
                            target:self  
                            action:@selector(backTo)] autorelease];  
    self.navigationItem.leftBarButtonItem = backButton;
Answer: We usually change the back button’s properties at the wrong place at the wrong time. The key is that we must add or change the back button’s title before we push the next controller. Then the next controller will use this ‘back’ button to return. You want to change the “look” (i.e. the image) of the back button. As a solution, in the given view controller, we can properly prepare and assign a new navigationItem.leftBarButtonItem value, but not the way you wanted. First make some background images for the back button in a few states and think ahead of orientation changes. The width and height is around 50×25 pixels. Add them to your project. In your code put them in a custom UIButton subclass with the appropriate styles and delegate. Assign this custom view to the navigationItem.leftBarButtonItem. These are the steps you missed.
// In your view controller:

- (void)loadView
{
    // Create an UIButton
    UIButton *button = [UIButton buttonWithType: UIButtonTypeCustom];
    // Set its background image for some states...
    [button setBackgroundImage: @"back-button.png" forState:UIControlStateNormal];  
    // Add target to receive Action
    [button addTarget: self action:@selector(backTo) forControlEvents:UIControlEventTouchUpInside];
    // Set frame width, height
    button.frame = CGRectMake(0, 0, 50, 26);  
    // Add this UIButton as a custom view to the self.navigationItem.leftBarButtonItem
    self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView: button] autorelease];  
}
Notes: If you want to change the background of the navigation bar, do not try to directly manipulate its subviews. Your third, fourth… controller’s navbar will not display it correctly. Once you push or pop a controller onto the navigation controller’s stack, the background imageview blocks out the title and navigation bar buttons. You are expected to use a navigation item, that is an instance of the UINavigationItem class, to specify what buttons or custom views you want displayed. Manipulate the navigationItem.titleView instead to present a “background”, and adjust the background color or image of the left and right buttons. When you want to control everything, than you have to implement a category for the UINavigationBar. Look at this Category solution:
// Your actual NavigationBar that you want to manipulate
#define MyNavBarTag    201889  

// Set it to your image file (from the bundle)
#define NavBarBackgroundImage    @"navbarbgrnd.png"
...

// UINavigationBar category
@implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
    // if( self.tag == MyNavBarTag ){     // You can avoid unwanted side effects in your app
        UIImage *image = [UIImage imageNamed: NavBarBackgroundImage];
        [image drawInRect: CGRectMake(0, 0, self.frame.size.width, self.frame.size.height) ];
    // }else{
    //    [super drawRect:rect];
    // }
}
@end
You should not use this Category example for your iOS 4.3 and later projects. Read this blog for more: Subclassing UINavigationBar in iOS 5 projects. References: UINavigationBar Class Reference UIBarButtonItem Class Reference