Reference the back button on UINavigationBar - ios

I need a reference to the back button in the UINavigationBar or UINavigationItem. The Back button in the image below.
I am not customizing the button, thus
navigationItem.backBarButtonItem
navigationItem.leftBarButtonItem
these both are nil.
Is there any way to get a reference to the button without customizing it?
Reference:
backBarButtonItem
leftBarButtonItem
Update: My comment might help to understand why I don't want to customize the back button. :)

The Documentation says this about the backBarButtonItem:
When this item is the back item of the navigation bar—when it is the
next item below the top item—it may be represented as a back button on
the navigation bar. Use this property to specify the back button. The
default value is a button displaying the navigation item’s title.
So the backBarButtonItem is always nil by default because it belongs to the previous view controller. The only way to get a non-nil reference is by customizing it.
If you just want to change the name, however, that can be done in the previous View Controller.

In reference to my use case - Ayush's comment
Till the time I get a concrete solution, I have created a dummy view below the navigation bar (below the back button) to show the tip from. Here is the code.
let v = UIView(frame: CGRectMake(0, 0, 50, 0))
view.addSubview(v)
let tipText = "Here it the back button"
EasyTipView.showAnimated(true,
forView: v,
withinSuperview: view,
text:tipText,
preferences: nil,
delegate: self)

try out this one
let backItem = UIBarButtonItem(title: "Custom Text HERE", style: .Bordered, target: nil, action: nil)
navigationItem.backBarButtonItem = backItem

Try this it might help you.
UINavigationItem *i = [self.navigationController.navigationBar.items firstObject];
i.title = #"Hai";

Related

Swift 4 Change UIBarButtonItem System Icon not working

I have two UIBarButtonItems inside my Navigation Item's Right Bar Button Items. I am looking to changing the second UIBarButtonItem only programmatically.
I have created an outlet for this UIBarButtonItem:
#IBOutlet var downloadButton: UIBarButtonItem!
and then I tried to change it like so:
self.downloadButton = UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(PlayerController.downloadButtonPressed(_:)))
But the UIBarButtonItem does not change over, what am I doing wrong?
But the UIBarButtonItem does not change over
There's no reason why it would. All you're doing is replacing the value of a variable downloadButton with a new bar button item. This has no effect on the bar button item still sitting there in the navigation bar — plus, you have destroyed your reference to that bar button item.
You have to reconfigure your navigationItem. You can also set your downloadButton again if you like, but more likely you'll realize you never needed the downloadButton outlet for anything in the first place.
Here's an example from one of my own apps, where I toggle the right bar button item between being a Play button and being a Pause button:
let whichButton : UIBarButtonItem.SystemItem? = {
switch self.mp.currentPlaybackRate {
case 0..<0.1:
return .play
case 0.1...1.0:
return .pause
default:
return nil
}
}()
if let which = whichButton {
let bb = UIBarButtonItem(barButtonSystemItem: which,
target: self, action: #selector(doPlayPause))
self.navigationItem.rightBarButtonItem = bb
}
Notice the last line: I just reach right in and change the navigationItem. Instantly the navigation bar display changes to match.

Custom back bar item button

Rather than going back 1 view controller, I am attempting to pop back to the first view controller under the navigation controller.
func setupBackBarButtons() {
let myBackButton = UIButton()
myBackButton.addTarget(self, action: #selector(presentListController), forControlEvents: .TouchUpInside)
let myCustomBackButtonItem = UIBarButtonItem(customView: myBackButton)
self.navigationItem.backBarButtonItem = myCustomBackButtonItem // This works
self.navigationItem.leftBarButtonItem = myCustomBackButtonItem // This doesn't.
}
func presentListController() {
navigationController?.popToViewController((self.navigationController?.viewControllers[0])!, animated: true)
}
I'm slightly confused to why I can add the custom button to the leftBarButtonItem but not the backBarButtonItem.
I only want to add a target to pop it back to the first view controller but not change the title (Still keep it as back with the < in the in corner). I would do this with the leftBarButtonItem but I'm not to sure how to keep the < in the title.
Do not change the functionality of the back button. When you try to do that, you just break the back button. You can customize the back button's appearance but you cannot change its action. You must provide a nil action and target so that the back button will still work as a back button.
To customize the back button's behavior, change the behavior of the navigation controller itself. Give the navigation controller a delegate and implement navigationController:didShowViewController:animated:. In your implementation, look to see how we got here. If we got here because we popped to it, pop further (to the root).

Set custom nav back button with multiple navigation controllers

I have a tab bar controller that has 5 tabs, each with a navigation controller embedded in. There are times where I need to display a view controller from another tab.
I am overriding the stock back button text < BACK to just have it say <, which I do using
let backItem = UIBarButtonItem()
backItem.title = ""
navigationController?.navigationBar.tintColor = UIColor.whiteColor()
navigationItem.backBarButtonItem = backItem
However, when I load a view controller from a different tab bar (with a different navigation controller), I can't figure out how to remove the < BACK from the supplementary navigation controller so I can just display the button as <. Putting the above code in prepareForSegue: works with one nav controller, but not when there is a second one. Thanks a lot, any insight is greatly appreciated!
The back button that you see when a view controller is pushed onto the navigation controller's stack belongs, not to the pushed view controller, but to the previous view controller, the one that was showing before the push.
If that view controller says:
self.navigationItem.backBarButtonItem =
UIBarButtonItem(title: "", style: .Plain, target: nil, action: nil)
... then when a view controller is pushed on top of it, the back button will show no title.

Placement of backbutton in navigation controller

I'm using a navigation controller, and I want to replace the default back button and text, with a custom. Here is what I do:
navigationItem.backBarButtonItem = UIBarButtonItem(title: "back", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
navigationController?.navigationBar.backIndicatorImage = UIImage(named: "BackCarretIcon")
navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "BackCarretIcon")
This is set in prepare for segue, before navigating away from the root view controller.
When the next view controller appears, the image appears to be in the right place, but when the push animation has completed, the back button image moves a bit down. See image of the destination view controller:
So the "BackCarretIcon" and "back" label are not vertical center alligned. How come?? and how can this be fixed.
There is no code in the view controller life cycle methods of the destination view controller, that uses the navigationcontroller or navigation items.
EDIT
I've put a breakpoint in viewWillLayoutSubviews in the destination view controller. It breaks two times, before the destination view controller appears on screen. When i continue execution after the second break, the destination view controller is pushed onto the screen(with the back carret in the right place). When it is fully pushed onto the screen, the back carret jumps a couple of points down, to the wrong position, and viewWillLayoutSubviews breaks again.
I'm not able to break, at the place where the back carret is positioned right...
Try this:
navigationController?.navigationItem.backBarButtonItem?.setTitlePositionAdjustment(UIOffset(horizontal: 0, vertical: -2), forBarMetrics: UIBarMetrics.Default)
Back button is property of the second last VC in the stack of VCs of navigation view controller.
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"BackBack" style:UIBarButtonItemStylePlain target:nil action:nil];
Put this in a child VC in a navigation VC & push another VC on top to it. Back button will display "BackBack". So proper way to do this would be to do this for every child VC. Here user will know that last VC was about "BackBack". But try not to do this. Inform user about where back button will take them. Hacking the way back button works might not be best way & might cause some problem.
Hope this helps.

iOS / Xcode - Navigation Item BackBarButtonItem title shows the one of the previous controller

i have 2 View Controllers connected by a segue within a Navigation Controller and I edited the back items titles in Interface Builder.
My problem is, that the BackBarButtonItem of the second controller shows the title of the first (and presenting) controller's BackBarButtonItem, no matter what I set for Back on the second controller's NavigationItem.
The only thing I've done is setting the leftBarButtonItem for the first Controller:
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: UIBarButtonItemStyle.Plain, target: self, action: "backTapped:")
Now all NavigationItems of presented Controllers show "Close". Does anyone have an idea, what's going on?
Thanks in advance
You have to configure desired back button item title on the view controller to which back will be performed, e.g. on previous one.

Resources