Customize the Back Button of UINavigationItem in the Navigation Bar
I’ve recently noticed a pattern of developers having trouble customizing the back button in the navigation bar. If you’re reading this, the problem may sound familiar.
When you use a UINavigationController to create a navigation stack, iOS conveniently and automatically creates a back button having the title that is the title of the previous view controller or the word Back if the previous view controller has no title. Of course, many times you want to override that default title or perhaps even use an image in its place. Let’s use Apple’s Master-Detail Application template as an example.
Let’s assume that instead of the word back or the title of the MasterViewController, you wanted to use the word Previous. You’ve looked at the UINavigationItem documentation and so in the
-viewDidLoad method DetailViewController, you create an instance of UIBarButtonItem with the title Previous, and then set the
backBarButtomItem of the detail view controllers’s UINavigationItem to this bar buttom item you created.
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Previous" style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backButtonItem;
You then run your app and ¡Viola! … a big disappointment as nothing seemed to happen. You’ve double-checked your code, you read the docs again, you move the statements to
viewDidLoad and still nothing.
So what most developers do that have gotten stuck here is create a custom bar button item and set the left button of the navigation item to it. However, then you get a square button instead of the button with the triangular end. So then the graphics designer gets involved and creates a custom image which developers then use to create a custom UIButton to use as a custom view for the hand-spun back button. The developers aren’t happy with it, it seems like a hack, especially given that Apple’s documentation clearly says you can customize the back button! WTF???
Now I think that taken as a whole, Apple’s documentation of the Cocoa and iOS frameworks are the best of any framework documentation. Easy to read, very description, easy to navigate (although, I wonder why searching web version is so much faster than the local version within Xcode). Occasionally, however, Apple makes you read between the lines when an additional sentence or two would save some developers a few hair-pulling incidents. The documentation for the `backButtonItem` property is one of those times. Let’s look at the description:
When this navigation item is immediately below the top item in the stack, the navigation controller derives the back button for the navigation bar from this navigation item. When this property is
nil, the navigation item uses the value in its title property to create an appropriate back button. If you want to specify a custom image or title for the back button, you can assign a custom bar button item (with your custom title or image) to this property instead. When configuring your bar button item, do not assign a custom view to it; the navigation item ignores custom views in the back bar button anyway.
It’s very important to read the first sentence carefully, “When this navigation item is immediately below the top item in the stack… .” What this is saying, and what developers sometimes miss, is that the back button is NOT set in navigation item of the visible view controller, but instead, it is set in the navigation item of the previous view controller. This throws everyone off because the rest of the items in the navigation bar is controlled by the navigation item of the visible view controller. As you can see, the documentation says that the back button in the bar is derived from the back button item in the navigation item immediately below the top item in the stack.
Going back to the MasterDetail example application, this means that the statements in the
-viewDidLoad statement belong in the
-viewDidLoad method in MasterViewController.
Also, make sure to notice that you cannot create a custom view to use for the back button. Custom views are ignored. You can still set the background image of the back bar button item with the