6

I made an app in iOS 7 and when I switched to Xcode 6.1 & iOS 8.1 my custom back buttons no longer appeared and they instead just showed the previous view controllers title--which is the default.

I am using:

self.navigationItem.backBarButtonItem.title = @"";
self.navigationItem.backBarButtonItem.tintColor = [UIColor whiteColor];

This is no longer working, I made sure to set delegates... (in .h & .m respectively)

.h

<UINavigationControllerDelegate, UINavigationBarDelegate>

.m

 self.navigationController.delegate = self;

I don't know if you do this differently in iOS8, I searched the boards and could only seem to figure out how to hide the back button. I know you have to set the back button text in the parent VC so to cover myself I included identical code in both VCs.

This code works so I know I have some ability to communicate with my navbar so it isn't like I have a problem there...

self.navigationItem.title = @"New <type>";

Thanks

Eli Whittle
  • 1,084
  • 1
  • 15
  • 19
  • Are you trying to make a custom back button, or just change the text of the back button on the nav bar of one of your view controllers? – Alex Dec 29 '14 at 20:46
  • I'm just trying to change the text, sorry I should have made that more clear. – Eli Whittle Dec 29 '14 at 21:16

3 Answers3

9

Sometimes with barButtonItems you need to just make new ones, instead of modifying old ones. I tried your code and it did not work for me either. This worked

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    UIBarButtonItem *item = [[UIBarButtonItem alloc] init];
    item.title = @"Title";
    self.navigationItem.backBarButtonItem = item;
}

EDIT

This code needs to be in the previous view controller, not the view controller that has the back button. Ex. If viewController A segue's to viewController B and you want the back button on view controller B to say "Backy" instead of viewController A's title, then you actually put this code in viewController A, not viewController B

EDIT 2

To dynamically change the back button title of the view controller, replace the backBtn before you push a viewController, and give it the appropriate title.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    let barBtnItem = UIBarButtonItem()
    navigationItem.backBarButtonItem = barBtnItem
    if segue.identifier == "seg1" {
        barBtnItem.title = "Hello 1"
    } else if segue.identifier == "seg2" {
        barBtnItem.title = "Hello 2"
    }
}
Alex
  • 3,861
  • 5
  • 28
  • 44
  • Sorry for delay, I'm about to try your code. Thanks! – Eli Whittle Dec 30 '14 at 19:37
  • 1
    @VanDuTran I updated my answer to explain where to put the code – Alex Nov 30 '15 at 19:46
  • I see. Thanks. If my viewController A can push viewController B and viewController C, do you know if there's a way to give viewController B and viewController C a different back button title? – Van Du Tran Dec 01 '15 at 18:31
  • @VanDuTran Change viewController A's backButton (affects viewController B), and change viewController B's back button (affects viewController C). – Alex Dec 01 '15 at 19:58
  • @Alex sorry, i was not clear. I meant, viewController A can push viewController B, and viewController A can push viewController C. So viewController A is the parent of both B, and C. – Van Du Tran Dec 01 '15 at 22:36
4

I needed four things [Swift]

  • Use my custom back button image
  • Don't show any text (like "back", or "last controller's title")
  • System wide, e.g. all back buttons look like this
  • DRY (don't repeat yourself)

Also since I do this a lot, and it's so bizarrely complicated I have to look it up every time, I made a category.

in AppDelegate.appDidFinishLaunching.... call this:

UINavigationBar.customBackButtonSetup("iconBackArrow", hideText: true)

Add this extension in its own file, like UINavigationBar+CustomBackButton:

extension UINavigationBar {

    // call this once at app start
    class func customBackButtonSetup(backButtonImageName: String, hideText: Bool) {
        // Custom back button
        let insets = UIEdgeInsets(top: 0, left: 0, bottom: -2.5, right: 0) // might have to modify this to perfect vertical alignments
        let backIndicator = UIImage(named: backButtonImageName)!.imageWithRenderingMode(.AlwaysOriginal).imageWithAlignmentRectInsets(insets)
        UINavigationBar.appearance().backIndicatorImage = backIndicator;
        UINavigationBar.appearance().backIndicatorTransitionMaskImage = backIndicator

        if hideText {
            let barAppearace = UIBarButtonItem.appearance()
            barAppearace.setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -100), forBarMetrics:UIBarMetrics.Default)
        }

    }
}
n13
  • 6,843
  • 53
  • 40
2

iOS 8+ Swift version (can be converted to ObjC without much effort). This method preserves all advantages and behaviour of navigation bar related to standard back button (animation on pushing/popping, interactive pop gesture, etc)

// Call the code ONE TIME somewhere on app launch to setup custom back button appearance
UINavigationBar.appearance().tintColor = UIColor.blackColor()
// If you need custom positioning for your back button, in this example button will be 1 px up compared to default one
// Also only vertical positioning works, for horizontal add offsets directly to the image
let backImageInsets = UIEdgeInsetsMake(0, 0, -1, 0)
// Get image, change of rendering (so it preserves offsets made in file), applying offsets
let backImage = UIImage(named: "YourButtonImageAssetFileName")?.imageWithRenderingMode(.AlwaysOriginal).imageWithAlignmentRectInsets(backImageInsets)
// Setting images
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage

// Call EACH TIME BEFORE pushing view controller if you don't need title near your back button arrow
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
// Push controller
self.navigationController?.pushViewController(vc, animated: true)
Andrei Konstantinov
  • 6,971
  • 4
  • 41
  • 57