[ios] UINavigationBar custom back button without title

How can I customize the navigation back button in iOS 7 and above without title? (i.e. with the arrow only)

self.navigationItem.leftBarButtonItem = self.editButtonItem;

I'm just wondering if they have any self.backButtonItem;

OR

something like this?

self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
                   initWithBarButtonSystemItem:UIBarButtonSystemItemBACK 
                   target:self action:@selector(back)];

This question is related to ios user-interface uinavigationbar

The answer is


SWIFT 4

For those looking to create custom back buttons as well as have their title removed please use the following piece of code within the view controller that's pushing the new one:

self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "close")
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "close")
self.navigationItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)

For a more universal use, do the following:

  1. Create a universal function as follows:

    func addCustomizedBackBtn(navigationController: UINavigationController?, navigationItem: UINavigationItem?) {
        navigationController?.navigationBar.backIndicatorImage = UIImage(named: "close")
        navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "close")
        navigationItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
    }
    
  2. Then use it in the view controllers as follows:

    addCustomizedBackBtn(navigationController: self.navigationController, navigationItem: self.navigationItem)
    

You don't have access to the navigation backButtonItem with the way you want, you need to create your own back button like below:

- (void)loadView
{
    [super loadView];
    UIButton *backButton = [[UIButton alloc] initWithFrame: CGRectMake(0, 0, 44.0f, 30.0f)];
    [backButton setImage:[UIImage imageNamed:@"back.png"]  forState:UIControlStateNormal];
    [backButton addTarget:self action:@selector(popVC) forControlEvents:UIControlEventTouchUpInside];
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
}

And off course:

- (void) popVC{
  [self.navigationController popViewControllerAnimated:YES];
}

Set back button item title as empty String.

[self.navigationController.navigationBar.backItem setTitle:@""];


In the prepareForSegue: method of your first ViewController you set that views title to @"", so when the next view is pushed it will display the previous ViewController title which will be @"".

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    self.navigationItem.title = @" ";
}

The only problem with this is that when you hit the back button your previous view won't have a title, so you may add it again on viewWillAppear:

-(void)viewWillAppear:(BOOL)animated{
   self.navigationItem.title = @"First View Title";
}

I don't like very much this solution but it works and i didn't find other way to do it.


You can change the title to @"" of the current ViewController on viewWillDisappear, and when it's about to show again re-set the title to whatever it was before.

-(void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.title = @"Previous Title";
}

-(void) viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.title = @"";
}

This works, but it will remove the title of the previous item, even if you pop back to it:

self.navigationController.navigationBar.topItem.title = @"";

Just set this property on viewDidLoad of the pushed View Controller.


Target: customizing all back button on UINavigationBar to an white icon

Steps: 1. in "didFinishLaunchingWithOptions" method of AppDelete:

UIImage *backBtnIcon = [UIImage imageNamed:@"navBackBtn"];


if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
    [UINavigationBar appearance].tintColor = [UIColor whiteColor];
    [UINavigationBar appearance].backIndicatorImage = backBtnIcon;
    [UINavigationBar appearance].backIndicatorTransitionMaskImage = backBtnIcon;
}else{

    UIImage *backButtonImage = [backBtnIcon resizableImageWithCapInsets:UIEdgeInsetsMake(0, backBtnIcon.size.width - 1, 0, 0)];
    [[UIBarButtonItem appearance] setBackButtonBackgroundImage:backButtonImage  forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];

    [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -backButtonImage.size.height*2) forBarMetrics:UIBarMetricsDefault];
}

2.in the viewDidLoad method of the common super ViewController class:

 if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@""
                                                                     style:UIBarButtonItemStylePlain
                                                                    target:nil
                                                                    action:nil];
        [self.navigationItem setBackBarButtonItem:backItem];
    }else{
        //do nothing
    }

This did the trick for me

[[UIBarButtonItem appearance] 
setBackButtonTitlePositionAdjustment:UIOffsetMake(-1000, -1000) 
forBarMetrics:UIBarMetricsDefault];

All the best


I have been using this solution since iOS 5 or so without any problems. I made a utility function that I call in my view controllers. You need to do it either in viewDidLoad or any point after that.

void updateBackButtonTextForViewController(UIViewController *viewController, NSString *text)
{
    if(! viewController.navigationItem.backBarButtonItem)
    {
        viewController.navigationItem.backBarButtonItem =
        [[UIBarButtonItem alloc] initWithTitle:text
                                         style:UIBarButtonItemStylePlain
                                        target:nil action:nil];
    }
    else
    {
        viewController.navigationItem.backBarButtonItem.title = text;
    }
}

In some cases the navigation item may already exist, in other cases it needs to be created. This accounts for both of those cases without messing with the navigation item title. It allows you to remove the title by simply passing in @"".


This works a treat for both iOS6 and 7

Xamarin(C#) options

var buttonStyleItems = UIBarButtonItem.AppearanceWhenContainedIn(typeof(SettingsNavigationController));
buttonStyleItems.SetBackButtonTitlePositionAdjustment(new UIOffset(-1000, -1000), UIBarMetrics.Default);

Objective-C option

[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(-1000, -1000) forBarMetrics:UIBarMetricsDefault];


All the answers do not solve the issue. It is not acceptable to set back button title in every view controller and adding offset to the title still makes next View Controller title shift to the right.

Here is the method using method swizzling, just create new extension to UINavigationItem

import UIKit

extension UINavigationItem {
    public override class func initialize() {

    struct Static {
        static var token: dispatch_once_t = 0
    }

    // make sure this isn't a subclass
    if self !== UINavigationItem.self {
        return
    }

    dispatch_once(&Static.token) {
        let originalSelector = Selector("backBarButtonItem")
        let swizzledSelector = #selector(UINavigationItem.noTitleBackBarButtonItem)

        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

        let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))

        if didAddMethod {
            class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }
}

// MARK: - Method Swizzling

struct AssociatedKeys {
    static var ArrowBackButtonKey = "noTitleArrowBackButtonKey"
}

func noTitleBackBarButtonItem() -> UIBarButtonItem? {
    if let item = self.noTitleBackBarButtonItem() {
        return item
    }

    if let item = objc_getAssociatedObject(self, &AssociatedKeys.ArrowBackButtonKey) as? UIBarButtonItem {
        return item
    } else {
        let newItem = UIBarButtonItem(title: " ", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
        objc_setAssociatedObject(self, &AssociatedKeys.ArrowBackButtonKey, newItem as UIBarButtonItem?, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        return newItem
    }
}
}

This is how I do it and the simplest, works and most clear way to do it.

This works if embed on Navigation Controller

Swift 3

In viewDidLoad I add this to the View Controller you want the back button to be just arrow.

if let topItem = self.navigationController?.navigationBar.topItem {
   topItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}

The difference of this to @Kyle Begeman's answer is that you call this on the view controller that you want the back button to be just arrow, not on the pushing stack view controller.


I found an easy way to make my back button with iOS single arrow.

Let's supouse that you have a navigation controller going to ViewA from ViewB. In IB, select ViewA's navigation bar, you should see these options: Title, Prompt and Back Button.

ViewA navigate bar options

ViewA navigate bar options

The trick is choose your destiny view controller back button title (ViewB) in the options of previous view controller (View A). If you don't fill the option "Back Button", iOS will put the title "Back" automatically, with previous view controller's title. So, you need to fill this option with a single space.

Fill space in "Back Button" option

Fill space in "Back Button" option

The Result:

The Result:


Simple hack from iOS6 works on iOS7 too:

[UIBarButtonItem.appearance setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault];

Edit: Don't use this hack. See comment for details.


you can use this. This works perfectly for me by just adding a UIButton as a custumview for the UIBarButtonItem.

Try the Below Code

    self.navigationItem.leftBarButtonItem=[self backButton];


- (UIBarButtonItem *)backButton
{
    UIImage *image = [UIImage imageNamed:@"back-btn.png"];
    CGRect buttonFrame = CGRectMake(0, 0, image.size.width, image.size.height);

    UIButton *button = [[UIButton alloc] initWithFrame:buttonFrame];
    [button addTarget:self action:@selector(backButtonPressed) forControlEvents:UIControlEventTouchUpInside];
    [button setImage:image forState:UIControlStateNormal];

    UIBarButtonItem *item= [[UIBarButtonItem alloc] initWithCustomView:button];

    return item;
}

iOS7 has new interface rules, so It's better to keep at least the back arrow when you push a UIView. It's very easy to change the "back" text programmatically. Just add this code before push the view (Or prepareForSegue if you are using StoryBoards):

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
      self.navigationItem.backBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:@"NEW TITLE" style:UIBarButtonItemStylePlain target:nil action:nil];
}

This will change the default "Back" text, but will keep the iOS7 styled back arrow. You can also change the tint color for the back arrow before push the view:

- (void)viewDidLoad{
     //NavBar background color:
     self.navigationController.navigationBar.barTintColor=[UIColor redColor];
//NavBar tint color for elements:
     self.navigationController.navigationBar.tintColor=[UIColor whiteColor];
}

Hope this helps you!


- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        // Custom initialization
        self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

    }
    return self; 
}

Just like Kyle Begeman does, you add the code above at your root view controller. All the sub view controller will be applied. Additionally, adding this in initWithCoder: method, you can apply the style for root view controllers in xib, storyboard or code based approaches.


Just use an image!

OBJ-C:

- (void)viewDidLoad {
     [super viewDidLoad];
     UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"Icon-Back"]
                                                                                        style:UIBarButtonItemStylePlain
                                                                                       target:self.navigationController
                                                                                       action:@selector(popViewControllerAnimated:)];
     self.navigationItem.leftBarButtonItem = backButton;
}

SWIFT 4:

let backBTN = UIBarButtonItem(image: UIImage(named: "Back"), 
                              style: .plain, 
                              target: navigationController, 
                              action: #selector(UINavigationController.popViewController(animated:)))
navigationItem.leftBarButtonItem = backBTN
navigationController?.interactivePopGestureRecognizer?.delegate = self

Icon-Back.png

Icon-Back

[email protected]

Icon-Back@2x

[email protected]

Icon-Back@23x


To add to Thomas C's answer above, sometimes putting a single space doesn't work and you have to keep adding spaces.

empty bar button

You'll know you succeeded when you see "Bar Button Item - " under the "Navigation Item". That's in the Document Outline (Editor->Show Document Outline). Once you see the above picture, you can delete a few spaces and see if it still works.


EDIT: 2014-04-09: As I gained reputations, I feel sorry because I don't use this trick any more. I recommend Kyle's answer. Also notice that the self of self.navigationItem.backBarButtonItem isn't the view controller the back button is displayed, but the previous view controller to be went back.

If you don't need to have title text for the previous view controller, just fill the title with a blank string;

self.navigationItem.title = @"";
[self.navigationController pushViewController:viewController animated:YES];

This will prevent showing "back" with chevron on the pushed view controller.

EDIT: Even you use non-blank title text, setting the title of the previous view controller in viewWillAppear: works except the title can flicker in a blink when view controller popped. I think "The twitter app" seems to do more subtle hack to avoid the flicker.


You may place that category in AppDelegate.m file. to removes text from all default back buttons in UINavigation. Only the arrow "<" or set custom image if you need.

Objective-c:

...

@end

@implementation UINavigationItem (Extension)

- (UIBarButtonItem *)backBarButtonItem {

    return [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
}

@end

 // add left bar button item

try this code:

- (void)viewDidLoad
{ 
    [super viewDidLoad];

   UIImage* image_back = [UIImage imageNamed:@"your_leftarrowImage.png"];
    CGRect backframe = CGRectMake(250, 9, 15,21);
    UIButton *backbutton = [[UIButton alloc] initWithFrame:backframe];
    [backbutton setBackgroundImage:image_back forState:UIControlStateNormal];
    [backbutton addTarget:self action:@selector(Btn_back:)
         forControlEvents:UIControlEventTouchUpInside];
    [backbutton setShowsTouchWhenHighlighted:YES];
    UIBarButtonItem *backbarbutton =[[UIBarButtonItem alloc] initWithCustomView:backbutton];
    self.navigationItem.leftBarButtonItem=backbarbutton;
    [backbutton release];

}
-(IBAction)Btn_back:(id)sender
{
    [self.navigationController popViewControllerAnimated:YES];

}

I'm written an extension to make this easier:

extension UIViewController {

    /// Convenience for setting the back button, which will be used on any view controller that this one pushes onto the stack
    @objc var backButtonTitle: String? {
        get {
            return navigationItem.backBarButtonItem?.title
        }
        set {
            if let existingBackBarButtonItem = navigationItem.backBarButtonItem {
                existingBackBarButtonItem.title = newValue
            }
            else {
                let newNavigationItem = UIBarButtonItem(title: newValue, style:.plain, target: nil, action: nil)
                navigationItem.backBarButtonItem = newNavigationItem
            }
        }
    }

}

While Kyle Begeman's answer totally does the trick, it is quite annoying to have this code in every view controller possible. I ended up with a simple UINavigationItem category. Beware, here be dragons! Sorry, I mean, swizzling:

#import <objc/runtime.h>

@implementation UINavigationItem (ArrowBackButton)

static char kArrowBackButtonKey;

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method m1 = class_getInstanceMethod(self, @selector(backBarButtonItem));
        Method m2 = class_getInstanceMethod(self, @selector(arrowBackButton_backBarButtonItem));
        method_exchangeImplementations(m1, m2);
    });
}

- (UIBarButtonItem *)arrowBackButton_backBarButtonItem {
    UIBarButtonItem *item = [self arrowBackButton_backBarButtonItem];
    if (item) {
        return item;
    }

    item = objc_getAssociatedObject(self, &kArrowBackButtonKey);
    if (!item) {
        item = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:NULL];
        objc_setAssociatedObject(self, &kArrowBackButtonKey, item, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return item;
}

@end

The only way that worked for me was:

navigationController?.navigationBar.backItem?.title = ""

UPDATE:

When I changed the segue animation flag to true (It was false before), the only way that worked for me was:

navigationController?.navigationBar.topItem?.title = ""

Set back title empty

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@""  style:UIBarButtonItemStyleDone target:self action:@selector(handleBack:)];
[backButton setTintColor:Color_WHITE];
[self.navigationItem setBackBarButtonItem:backButton];

Change back image

 UIImage *backImg = [[UIImage imageNamed:@"ic_back_white"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[UINavigationBar appearance].backIndicatorImage = backImg;
[UINavigationBar appearance].backIndicatorTransitionMaskImage = backImg;

You can subclass UINavigationController, set itself as the delegate, and set the backBarButtonItem in the delegate method navigationController:willShowViewController:animated:

@interface Custom_NavigationController : UINavigationController <UINavigationControllerDelegate>

@end

@implementation Custom_NavigationController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.delegate = self;
}

#pragma mark - UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController     willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    viewController.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
}

@end

I applied the following code in viewDidLoad and it works:

  // this will set the back button title
self.navigationController.navigationBar.topItem.title = @"Test";

 // this line set the back button and default icon color  

//[[self.navigationController.navigationBar.subviews lastObject] setTintColor:[UIColor blackColor]];

this line change the back default icon to your custom icon
[[self.navigationController.navigationBar.subviews lastObject] setTintColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"menuicon"]]];

Just to update I use Vector Icon


Create a UILabel with the title you want for your root view controller and assign it to the view controller's navigationItem.titleView.

Now set the title to an empty string and the next view controller you push will have a back button without text.

self.navigationItem.titleView = titleLabel; //Assuming you've created titleLabel above
self.title = @"";

It's actually pretty easy, here is what I do:

Objective C

// Set this in every view controller so that the back button displays back instead of the root view controller name
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];

Swift 2

self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)

Swift 3

self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)

Put this line in the view controller that is pushing on to the stack (the previous view controller). The newly pushed view controller back button will now show whatever you put for initWithTitle, which in this case is an empty string.


Nothing much you need to do. You can achieve the same through storyboard itself.

Just go the root Navigation controller and give a space. Remember not to the controller you wanted the back button without title, but to the root navigation controller.

As per the image below. This works for iOS 7 and iOS 8


  1. Add new UIBarButtonItem to UINavigationItem to left
  2. Change UIBarButtonItem how to want use
  3. Now, click UINavigationItem and swipe barBackButtonItem from outlets to left UIBarButtonItem

enter image description here


If you have two ViewController(FirstVC, SecondVC) Embed in Navigation Controller, and you want there is only back arrow in SecondVC.

You can try this In FirstVC's ViewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
}

Then when you push into SecondVC, you'll see the there is only back arrow


  • Change backItem.title = "" to using topItem.title = ""
  • Setting navigationItem.hidesBackButton = true & navigationItem.leftBarButtonItem will lose the back gesture
  • Remember we have to create 2 instances of the back image

My solution will change the image & keep the back gesture:

navigationController?.navigationBar.backIndicatorImage = UIImage(named: "back")
navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "back")
navigationController?.navigationBar.topItem?.title = ""

Check this answer

How to change the UINavigationController back button name?

set title text to string with one blank space as below

title = " "

Don't have enough reputation to add comments :)


If you set the tintColor Of NavigationBar,add a custom back button image without title that tint color will reflect the image color. Please follow this apple documentaion link.

https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/UIKitUICatalog/index.html#//apple_ref/doc/uid/TP40012857-UIView-SW7

UINavigationItem *navItem = [[UINavigationItem alloc] init];
   navBar.tintColor = self.tintColor;

   UIImage *myImage = [UIImage imageNamed:@"left_arrow.png"];
     myImage = [myImage              imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

     UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithImage:myImage style:UIBarButtonItemStylePlain target:self action:@selector(cancelButtonFunction:)];
     navItem.leftBarButtonItem = leftButton;

    navBar.items = @[ navItem ];

Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to user-interface

Calling another method java GUI How do I center text vertically and horizontally in Flutter? Is it possible to put a ConstraintLayout inside a ScrollView? How to change color of the back arrow in the new material theme? How to create RecyclerView with multiple view type? Android RecyclerView addition & removal of items tkinter: how to use after method Presenting a UIAlertController properly on an iPad using iOS 8 Android ViewPager with bottom dots How do I get the height and width of the Android Navigation Bar programmatically?

Examples related to uinavigationbar

Swift programmatically navigate to another view controller/scene How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem? How to hide a navigation bar from first ViewController in Swift? Change color of Back button in navigation bar NavigationBar bar, tint, and title text color in iOS 8 transparent navigation bar ios presenting ViewController with NavigationViewController swift Changing navigation title programmatically Navigation bar with UIImage for title Changing navigation bar color in Swift