124

I want to remove the text from the back button, but I want to keep the icon. I have tried

let backButton = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: navigationController, action: nil)
navigationItem.leftBarButtonItem = backButton

However, this removes completely the text and the icon.

Let's_Create
  • 2,963
  • 3
  • 14
  • 33
lmiguelvargasf
  • 63,191
  • 45
  • 217
  • 228

32 Answers32

166

I know this already has an answer, but you can also do it in code (in case you're working with nibs)

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

Add the above in the first view controller.

Note that you need to do this for each view controller that is pushing. So if you have 3 view controllers, and you want to remove the back text from all of them, you'll have to add the line in view controller 1 and 2.

d9rad
  • 2,067
  • 1
  • 13
  • 7
109

The method of @rmd2 is almost right, but instead you should select the navigation bar of the controller to which back button will point to and type " " in the Back Button field.

enter image description here

Drise
  • 4,310
  • 5
  • 41
  • 66
m8labs
  • 3,671
  • 2
  • 30
  • 32
63

After Searching a lot I found best and simple solution, this will affect all the viewControllers written in Swift 4.2 and also working in Swift 5

extension UIViewController {
    open override func awakeFromNib() {
        navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
    }  
}

After iOS 14

extension UIViewController {
    open override func awakeAfter(using coder: NSCoder) -> Any? {
        navigationItem.backButtonDisplayMode = .minimal // This will help us to remove text
        return super.awakeAfter(using: coder)
    }
}
iOS Lifee
  • 2,091
  • 23
  • 32
40

If you wanted to remove the title of a back button from a pushed view controller...

let's say a class named SettingsVC is going to push SubSettingsVC then in the subSettingsVC back button will show a title <Settings so in order to remove the "settings" text from back button and make it something like <

you've to set backBarButtonItem title in SettingsVC's viewWillDisappear() method.

Objective-C:

- (void)viewWillDisappear:(BOOL)animated
    [super viewWillDisappear:animated];
    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:self.navigationItem.backBarButtonItem.style target:nil action:nil];
}

Swift:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
Muhammad Umair
  • 1,664
  • 2
  • 20
  • 28
  • 1
    `.Plain` was changed to `.plain`. No capital p. – Gal Jun 21 '17 at 11:12
  • 1
    The answer needs to be updated for searchController behavior. For instance, if you use a separate resultsVC and tap on an item that pushes another VC, the viewWillDisappear method from the initial searchController is not called, hence the title is still there – H4Hugo Apr 10 '18 at 08:20
  • This is not a good approach if you are looking for a solution for screens in the entire app. - If you add this code to some "Base View Controller", viewWillDisappear of first view controller will be called after viewDidAppear of second view controller (where you usually set title)... this will mess up the titles. Best way is to overwrite back button – Mithra Singam Jul 15 '18 at 18:09
  • Perfect Solution Thanks – SURESH SANKE Dec 28 '18 at 06:19
38

The text of the back button depends on the title of the master view.

The trick is to clear the title if the master view disappears and set it again if it is shown again:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    // needed to clear the text in the back navigation:
    self.navigationItem.title = " "
}

override func viewWillAppear(_ animated: Bool) {
   
    super.viewWillAppear(animated)
    self.navigationItem.title = "My Title"
}
Maximilian
  • 463
  • 5
  • 16
Stefan
  • 5,203
  • 8
  • 27
  • 51
31

If you want back arrow so following code put into AppDelegate file into didFinishLaunchingWithOptions method.

For Swift

let BarButtonItemAppearance = UIBarButtonItem.appearance()
BarButtonItemAppearance.setTitleTextAttributes([.foregroundColor: UIColor.clear], for: .normal)
vrwim
  • 13,020
  • 13
  • 63
  • 118
Pradeep Bishnoi
  • 1,843
  • 2
  • 22
  • 26
  • 2
    i like this one because you can standardize the style of your app in a single file and call it once from the app delegate – aaronium112 May 30 '18 at 18:16
  • 4
    It's really nice and fast solution, But... it's could be tricky if you've other bar button items except the back one : ) – vhristoskov Nov 22 '18 at 13:31
  • 3
    One observation, if you only implement the ".normal" attribute, you will see the text on click. Add the same line for ".selected", ".highlighted", and ".disabled." to ensure you don't see the flicker text. – Nick N Dec 29 '18 at 06:54
  • 1
    I think this will have a side effect, other bar buttons aside from back buttons will also be affected and will have a clear text color :( – dhin Jun 17 '19 at 06:59
27

In my case, for custom icon and title this did the trick (Swift 4)

    let imgBack = UIImage(named: "ic_back")

    navigationController?.navigationBar.backIndicatorImage = imgBack
    navigationController?.navigationBar.backIndicatorTransitionMaskImage = imgBack

    navigationItem.leftItemsSupplementBackButton = true
    navigationController?.navigationBar.topItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: self, action: nil)
Rafiqul Hasan
  • 3,324
  • 4
  • 20
  • 28
  • 1
    the last line in that code worked flawlessly for me. All the other suggestions did not work, probably because my view controllers are all controlled by a nav controller. In which case, the navigationController? is really required. – Salx Nov 13 '18 at 19:19
  • You will need top four line if you want to add a custom back button. Otherwise last line will did the trick. – Rafiqul Hasan Nov 14 '18 at 06:02
24

This is working for me

override func viewDidLoad() {
    super.viewDidLoad()
    navigationController?.navigationBar.topItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
Malathi
  • 2,119
  • 15
  • 40
RomanV
  • 549
  • 4
  • 6
14

I solved this problem by adding a " " on the StoryBoard Title of the previous ViewController. Just a space, not empty ;D

enter image description here

rmd2
  • 157
  • 3
14

Finally found perfect solution.

Just add one transparent Image and add following code in your AppDelegate.

UIBarButtonItem.appearance().setBackButtonBackgroundImage(#imageLiteral(resourceName: "transparent"), for: .normal, barMetrics: .default)
Kumar
  • 1,882
  • 2
  • 27
  • 44
  • 1
    This is definitely the best answer. I was previously using the `UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment` hack most other answers recommend, but it was broken on iPhone X for view controllers with long titles. This solution works flawlessly. – Ned May 29 '18 at 21:50
  • 3
    Best answer. Worked better than transparent text color. – William T. May 31 '18 at 06:52
  • 1
    Best solution what I used in last 4 years! You do it once, in one place and for all viewcontrollers!!! – korgx9 Aug 30 '18 at 05:56
  • 1
    When I tried this with iOS 12, the text still appeared next to the image. :( – Sean McMains Nov 02 '18 at 14:53
12

in swift 4

self.navigationController?.navigationBar.topItem?.title = ""
Amalendu Kar
  • 458
  • 1
  • 6
  • 17
11

For Swift 4+ put these lines into AppDelegate at didFinishLaunchingWithOptions

let BarButtonItemAppearance = UIBarButtonItem.appearance()

BarButtonItemAppearance.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.clear], for: .normal)      
BarButtonItemAppearance.setBackButtonTitlePositionAdjustment(UIOffsetMake(-200, 0), for:UIBarMetrics.default)
Emre YILMAZ
  • 152
  • 2
  • 10
BilalReffas
  • 8,132
  • 4
  • 50
  • 71
  • When you set the appearance in the app delegate the clear foreground color is for every UIBarButtonItem, isn't it? So if I add an UIBarButtonItem with a text, do I have to change the foregroundcolor for this button manually? – kuzdu May 09 '18 at 07:12
  • 1
    This is good but when you press the back button it still shows the text – William T. May 31 '18 at 06:47
  • It work but make other bar button disappear in iOS 11. The answer from Rafiqul Hasan above can fix the problem – huynguyen Aug 20 '18 at 04:21
7

You can remove text from back button using a delegate method of UINavigationController.

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }

}

extension CustomNavigationController: UINavigationControllerDelegate {
    
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        viewController.navigationItem.backBarButtonItem = UIBarButtonItem(title: String(), style: .plain, target: nil, action: nil)
    }
    
}
Keval Vadoliya
  • 1,003
  • 1
  • 9
  • 17
6

If you have a ViewControllerA and you want to navigate to the ViewControllerB, in the ViewControllerA, you should set the current navigationItem with a new UIBarButtonItem and the title to a string with blank space before push to another view controller:

Set the title to a string with a blank space, you can't set nil or "" (empty string) because the default value is nil

let backItem = UIBarButtonItem()
backItem.title = " "
navigationItem.backBarButtonItem = backItem
let controllerB = ViewControllerB()
navigationController?.pushViewController(controllerB, animated: true)
Bradley
  • 455
  • 5
  • 11
  • I was getting some very funny behaviour with the "Back" text reappearing even when the title was set to " " (and inspected as such) in `ViewControllerB` (even though that had always worked up until now, with my particular edge case), this was the only solution that worked for me – 10623169 Sep 23 '20 at 09:03
5

Put this code in each VC which pushes another one

navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
Polina Hill
  • 141
  • 2
  • 3
4

To hide the back button text globally (iOS 14+):

extension UINavigationController {
  open override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    navigationBar.topItem?.backButtonDisplayMode = .minimal
  }
}
Andrew Stoddart
  • 408
  • 4
  • 9
3
let button: UIButton = UIButton (type: UIButtonType.Custom)
button.setImage(UIImage(named: "imageName"), forState: UIControlState.Normal)
button.addTarget(self, action: "backButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
button.frame = CGRectMake(0, 0, 30, 30)
let barButton = UIBarButtonItem(customView: button)

self.navigationItem.leftBarButtonItem = barButton

func backButtonPressed(btn : UIButton) {

    // Your code
}
Hasya
  • 9,792
  • 4
  • 31
  • 46
3

To remove from all viewcontrollers in a navigation controller stack:

subclass UINavigationController and add this:

override func show(_ vc: UIViewController, sender: Any?) {
    setEmptyBackButton(vc)
    super.show(vc, sender: sender)
}

override func pushViewController(_ viewController: UIViewController, animated: Bool) {
    setEmptyBackButton(viewController)
    super.pushViewController(viewController, animated: animated)
}

func setEmptyBackButton(_ viewController: UIViewController) {
    viewController.navigationItem.backBarButtonItem =
        UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
Gaston Gonzalez
  • 427
  • 3
  • 6
3

Xcode 10, Swift 4+

Similar answer to the others here but it is worth noting that if the text still isn't cleared, you have to click Space then Enter.

enter image description here

oxsha
  • 233
  • 3
  • 9
2

You should select the navigation bar of the controller FROM which back button will point to and type " " in the Back Button field.

e.g if you are pushing A controller to B controller, put whitespace in A controller navigation bar.

2

Sometimes its not working to change only the title color, in case when the title is long. Because it might shift the navigation bar title to the left. So to prevent it you might need to shift the bar button title horizontally in addition to make it transparent:

let barButtonItemAppearance = UIBarButtonItem.appearance()
    barButtonItemAppearance.setTitleTextAttributes([NSAttributedStringKey.foregroundColor: UIColor.clear], for: .normal)
    barButtonItemAppearance.setBackButtonTitlePositionAdjustment(UIOffsetMake(-200, 0), for:UIBarMetrics.default)
Max Niagolov
  • 684
  • 9
  • 26
2

This will solve your issue:

    import UIKit

    extension UINavigationController{

    func customizeBackArrow(){
        let yourBackImage = UIImage(named: "icon_back_arrow")
        self.navigationBar.backIndicatorImage = yourBackImage
        self.navigationBar.tintColor = Common.offBlackColor
        self.navigationBar.backIndicatorTransitionMaskImage = yourBackImage
        navigationItem.leftItemsSupplementBackButton = true
        self.navigationBar.topItem?.backBarButtonItem = UIBarButtonItem(title: "", 
           style: .plain, target: self, action: nil)

    }
}
mossman252
  • 462
  • 4
  • 3
2

I've tried a couple of answers and I can't get them to work in all cases. So this is a workaround to not affect the title of the navigation bar if it's set.

    guard let items = viewController.navigationController?.navigationBar.items else { return }
    for item in items {
        if item.title == nil {
            item.title = ""
        }
    }
2

Details

  • Xcode Version 10.2.1 (10E1001), Swift 5

Solution

1. Create custom class of the UINavigationController

import UIKit

class NavigationController: UINavigationController {
    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
    }
}

extension NavigationController: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        if viewController.navigationItemBackButtonTextIsHidden {
            viewController.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
        }
    }
}

2. Add UIViewController extension

import UIKit

extension UIViewController {
    @objc var navigationItemBackButtonTextIsHidden: Bool { return false }
}

3. Update your ViewController class

import UIKit

class ViewController: UIViewController {
    override var navigationItemBackButtonTextIsHidden: Bool { return true }
}

Full sample

import UIKit

// MARK: - ViewController

class ViewController: UIViewController {

    var screenCounter = 1

    override func viewDidLoad() {
        super.viewDidLoad()
        setupNavigationItem()
    }

    override var navigationItemBackButtonTextIsHidden: Bool { return (screenCounter % 2) == 0 }
}

extension ViewController {

    private func setupNavigationItem() {
        navigationItem.title = "VC \(screenCounter)"
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "push", style: .plain, target: self, action: #selector(pushBarButtonTouchedUpInside))
    }

    @objc func pushBarButtonTouchedUpInside(button: UIBarButtonItem) {
        guard let navigationController = navigationController else { return }
        let viewController = ViewController()
        viewController.screenCounter = screenCounter + 1
        viewController.view.backgroundColor = .white
        navigationController.pushViewController(viewController, animated: true)
    }
}

// MARK: - NavigationController

class NavigationController: UINavigationController {
    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
    }
}

extension NavigationController: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        if viewController.navigationItemBackButtonTextIsHidden {
            viewController.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
        }
    }
}

// MARK: - UIViewController extension

extension UIViewController {
    @objc var navigationItemBackButtonTextIsHidden: Bool { return false }
}

Result

enter image description here

Vasily Bodnarchuk
  • 24,482
  • 9
  • 132
  • 127
2

One alternative to override all ViewControllers for me was to extend UINavigationController and set the backBarButtonItem of the topViewController.

Swift 5 on Xcode 11.2.1:

extension UINavigationController {
    override open func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        let backButton = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil)
        self.topViewController?.navigationItem.backBarButtonItem = backButton
    }
}
Unlucky
  • 21
  • 3
2

The easy programmatic way, without unwanted side-effects, is initializing the navigationItem.backBarButtonItem with an empty item in the awakeFromNib method of the source controller (the one you are navigating from):

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

Note: If you initialized the back button later, like in the viewDidLoad() method, than you would lose swipe-back functionality (swiping from the left edge to the right takes you one step back in the navigation stack).

Then, if you want different back button texts for different destination controllers and if you're using segues, you can set the title in the prepare(for segue:, sender:) method, like this:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let item = navigationItem.backBarButtonItem {
        switch segue.identifier {
        case "SceneOne": item.title = "Back"; break
        case "SceneTwo": item.title = "Home"; break
        case "SceneThree": item.title = nil; break // Use this scene's title
        default: item.title = "" // No text
        }
    }
}
Jiri Volejnik
  • 1,034
  • 6
  • 9
2

The easiest way to do this programmatically is to set backBarButtonItem from the parent view controller (a controller that calls push).

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

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

More detail here https://sarunw.com/posts/how-to-remove-text-from-uinavigationbar-back-button/

sarunw
  • 8,036
  • 11
  • 48
  • 84
2

Swift 5 Version remove back button title and set custom Image ios 13.0+

 let backButtonAppearance = UIBarButtonItemAppearance(style: .plain)
        backButtonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.clear]
        let navigationBarAppearance = UINavigationBarAppearance()
        navigationBarAppearance.backButtonAppearance = backButtonAppearance
        navigationBarAppearance.setBackIndicatorImage(#imageLiteral(resourceName: "back"), transitionMaskImage: #imageLiteral(resourceName: "back"))
        UINavigationBar.appearance().standardAppearance = navigationBarAppearance

Add this code in App delegate didFinishLaucnh

Imran Rasheed
  • 825
  • 10
  • 25
2

After struggling a lot, the only thing that WORKDED for me was:

  1. Click on your button in Storyboard/Xib

  2. Since every button needs a name(even if you don't want to display it on the Ui), go to IdentityInspector[Cmd + Option + 4] and on {Document-Label} write a name for it.

  3. In the AttributeInspector[Cmd + Option + 5], change the {Style} from "Plain" to "Default", and the {Type} to "Custom".

  4. And since you aren't showing any text on the button Ui, In the AttributeInspector[Cmd + Option + 5] set an {Image} from you Assets.

Build, Run, and have a nice day!

1

For me this did the trick:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(true)
    self.navigationItem.title = " "
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationItem.title = "my amazing title"
    navigationItem.backBarButtonItem = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil)
}

Notice that if you only set the title without modifying the backBarButtonItem it will appear to work. But if you try to go back using a gesture and than cancel and stay on the pushed view controller, the back title will come back.

Working in Swift 4

mrc
  • 511
  • 5
  • 9
1

In Xcode 9.2 with Swift, it worked like this:

override func viewWillDisappear(_ animated: Bool) {
   super.viewWillDisappear(true)
   navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
Thiago Bueno
  • 171
  • 1
  • 4
0

For the case where we have not control at all of the previous view controller (i.e. if we are working in a framework), we can delete the title of the back button as follow:

// For iOS 10
navigationController?.navigationBar.items?.last?.backBarButtonItem?.title = String()

// For iOS 11
navigationController?.navigationBar.items?.last?.backBarButtonItem?.title = nil

What it does is to navigate to the last item of the navigation's stack and delete its back title. Make sure to save the original one when our view controller will appear:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    originalBackButtonTitle = navigationController?.navigationBar.items?.last?.backBarButtonItem?.title
    // Delete title somewhere here...
}

and then reassign it, in order to not disrupt any part of the app:

override func viewWillDisappear(_ animated: Bool) {
    navigationController?.navigationBar.items?.last?.backBarButtonItem?.title = originalBackButtonTitle
    super.viewWillDisappear(animated)
}
Ángel Téllez
  • 987
  • 9
  • 13