Using an image for the UISplitViewController popover button

A quick tip for something that I did not immediately find obvious. When using a UISplitViewController in portrait mode the detail view has a button created by the controller to allow access to the master view (see image below:)

The button is actually a UIBarButtonItem allocated by the split view controller. The view controller for the detail view must implement the UISplitViewControllerDelegate protocol which has two methods to control show and hide the button which are normally implemented something like this:

// Called when the view controller is changing to portrait mode.
// The button is added to the toolbar and the reference to the
// popover controller is saved.
- (void)splitViewController: (UISplitViewController*)svc
    willHideViewController:(UIViewController *)aViewController
    withBarButtonItem:(UIBarButtonItem*)barButtonItem
    forPopoverController: (UIPopoverController*)pc {

    barButtonItem.title = @"Root List";
  
    NSMutableArray *items = [[toolbar items] mutableCopy];
    [items insertObject:barButtonItem atIndex:0];
    [toolbar setItems:items animated:YES];
    [items release];
    self.popoverController = pc;
}

// Called when the view controller is changing to landscape mode.
// Hides the button and removes the popoverController
- (void)splitViewController: (UISplitViewController*)svc
    willShowViewController:(UIViewController *)aViewController
    invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
    NSMutableArray *items = [[toolbar items] mutableCopy];
    [items removeObjectAtIndex:0];
    [toolbar setItems:items animated:YES];
    [items release];
    self.popoverController = nil;
}

This works well when you only want a text button, but what happens if you want to an image or icon for the button. There are two methods for initialising a bar button item with an image: -initWithCustomView: or initWithImage:style:target:action. However with the split view controller the UIBarButtonItem has already been created and attempting to set the customView property after the fact does not seem to work.

The key is to realise that UIBarButtonItem inherits from UIBarItem which does have an image property we can set:

- (void)splitViewController: (UISplitViewController*)svc
    willHideViewController:(UIViewController *)aViewController
    withBarButtonItem:(UIBarButtonItem*)barButtonItem
    forPopoverController: (UIPopoverController*)pc {

    barButtonItem.image = [UIImage imageNamed:@"home.png"];
    barButtonItem.style = UIBarButtonItemStylePlain;
  
    NSMutableArray *items = [[toolbar items] mutableCopy];
    [items insertObject:barButtonItem atIndex:0];
    [toolbar setItems:items animated:YES];
    [items release];
    self.popoverController = pc;
}

Note that I also change the style of the button to be plain rather than bordered. The effect is as follows: