Remove text from Back button keeping the icon
Asked Answered
S

32

127

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.

Skirmish answered 8/10, 2015 at 20:20 Comment(1)
P
167

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.

Postwar answered 21/1, 2016 at 11:56 Comment(7)
This is the best solution I have seen so far gives me no troubleNorwich
.Plain was changed to .plain. No capital p.Reconstruction
Perfect..! Thats what I want.Marriageable
Best solution. Thanks.Kimmi
Best Solution! Perfect!Comparable
@GastónAntonioMontes, it does work on iOS13, but it's a bit counter intuitive: the empty title backBarButtonItem should be declared on the pushing view controller, not the pushed oneStickle
Nice, for my case I only want to remove back text from the second view controller, so this solution allows me to selectively remove the back text :) thanksMcinnis
B
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

Broom answered 8/10, 2015 at 21:7 Comment(1)
worst way, if the viewcontroller does not have the navigationbar I will have to add to remove the textHorney
R
68

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)
    }
}
Raster answered 11/1, 2019 at 9:26 Comment(7)
Works like charmSupreme
Note that this will only work if your ViewController is contained in a Storyboard or Nib...Beaudry
A genius solution!Harriettharrietta
But make sure that the navigation controller's bar button item's tint color is not "clear".Bowne
I did @objc but it not work any solution for Objective C ?Levan
This does not work for me. Check the solution below by @stefan, that will work for sure.Schenk
This used to work for me, but no longer (it still works on iOS 12 simulators, just not the latest iOS 13)...Arathorn
J
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)
}
Jaborandi answered 25/9, 2016 at 7:47 Comment(4)
.Plain was changed to .plain. No capital p.Reconstruction
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 thereAllegedly
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 buttonNodal
Perfect Solution ThanksMullet
W
40

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"
}
Wulfila answered 23/3, 2017 at 22:28 Comment(1)
Perfect! I didn't want to replace the default button.Alcott
J
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)
Jefferey answered 11/1, 2018 at 6:0 Comment(4)
i like this one because you can standardize the style of your app in a single file and call it once from the app delegateWorkaday
It's really nice and fast solution, But... it's could be tricky if you've other bar button items except the back one : )Dropline
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.Columella
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 :(Eclecticism
V
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)
Vocative answered 28/3, 2018 at 9:29 Comment(2)
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.Un
You will need top four line if you want to add a custom back button. Otherwise last line will did the trick.Vocative
M
25

This is working for me

override func viewDidLoad() {
    super.viewDidLoad()
    navigationController?.navigationBar.topItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
}
Monadism answered 9/7, 2019 at 6:15 Comment(2)
Correct one. In ios 13, navigationItem.backBarButtonItem not works. It saved my hours of efforts. ThanksElaina
this is the only one works with a searchViewController situationShellans
D
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

Domitian answered 8/10, 2015 at 20:25 Comment(3)
I need the previous screen to have a title, so I guess that is not going to work for me.Skirmish
I have blanked that title but still title is coming in back button titleHomeomorphism
don't blank the Title, field, put " " (space) in Back Button fieldTemperament
K
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)
Khan answered 15/2, 2018 at 7:5 Comment(4)
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.Crowley
Best answer. Worked better than transparent text color.Universe
Best solution what I used in last 4 years! You do it once, in one place and for all viewcontrollers!!!Carbolize
When I tried this with iOS 12, the text still appeared next to the image. :(Pirn
T
12

in swift 4

self.navigationController?.navigationBar.topItem?.title = ""
Tennison answered 28/11, 2018 at 6:33 Comment(3)
Thanks, it helped me out, (Swift 4.0, Xcode 10.1, iOS 12.1.1), thanksJurisdiction
BUT, you will lost your title in parent vcSarraceniaceous
If large title is present then topItem is largeTitle. Doesn't worksAmuck
I
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)
Impeditive answered 20/3, 2018 at 17:34 Comment(3)
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?Canadianism
This is good but when you press the back button it still shows the textUniverse
It work but make other bar button disappear in iOS 11. The answer from Rafiqul Hasan above can fix the problemApocalyptic
R
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)
    }
    
}
Remunerate answered 28/6, 2020 at 11:48 Comment(0)
I
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)
Interlineate answered 12/4, 2018 at 18:26 Comment(1)
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 meTadeas
C
5

Put this code in each VC which pushes another one

navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
Chadd answered 6/11, 2018 at 11:49 Comment(0)
B
5

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

extension UINavigationController {
  open override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    navigationBar.topItem?.backButtonDisplayMode = .minimal
  }
}
Biodegradable answered 22/11, 2022 at 14:18 Comment(0)
B
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
}
Barye answered 20/4, 2016 at 6:14 Comment(0)
W
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)
}
Whiffle answered 8/3, 2018 at 3:29 Comment(0)
F
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

Flagg answered 5/2, 2019 at 23:35 Comment(0)
B
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.

Bunyabunya answered 13/2, 2018 at 13:40 Comment(0)
T
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)
Trueblue answered 6/6, 2018 at 6:26 Comment(0)
D
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)

    }
}
Doyle answered 8/3, 2019 at 5:48 Comment(1)
No ups on this?! This is the correct way to do this as well! ThanksKrystalkrystalle
L
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 = ""
        }
    }
Lagging answered 22/3, 2019 at 7:49 Comment(0)
B
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

Boz answered 19/6, 2019 at 15:2 Comment(0)
U
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
    }
}
Uphemia answered 13/11, 2019 at 16:7 Comment(0)
W
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
        }
    }
}
Worldbeater answered 3/4, 2020 at 11:1 Comment(1)
This is the best way. Works in iOS 14 too.Inception
N
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/

Neutralization answered 31/5, 2020 at 13:22 Comment(0)
D
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

Dylan answered 18/3, 2021 at 10:58 Comment(0)
J
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! 😉🚀

Jocose answered 8/8, 2022 at 13:30 Comment(0)
N
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

Newcomer answered 30/1, 2018 at 13:50 Comment(2)
Could you explain?Newcomer
I have controller which is always showing Back text with back button. So above code not working in my caseUnitarian
V
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)
}
Valgus answered 10/8, 2018 at 9:56 Comment(0)
L
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)
}
Lasley answered 15/8, 2018 at 21:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.