Placement of backbutton in navigation controller - ios

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.

Related

UINavigationItem backBarButtonItem issue during screen transition

I have UINavigationController with 2 view controllers vc1 and vc2 (vc1 pushes vc2). I need to set back button title of vc2, so I do it by:
vc1.navigationItem.backBarButtonItem
= UIBarButtonItem(title: title, style: .plain, target: nil, action: nil)
But this back button title is a counter, I get it from Database, so I usually set it after viewWillAppear but before viewDidAppear (it happens during navigation controller transition from vc1 to vc2)
But the back button title is applied only after the transition is completed. As a comparison if I use leftBarButtonItem with custom view, the title is applied before the transition is completed. But I'm not allowed to use leftBarButtonItem
Here is the Video how it looks like (it's possible to notice if you scroll video slowly)
Is it possible somehow to force update back button title before the transition is completed?

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.

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.

UINavigationItem BackButton shows the same as the UINavigationItem?

In my UINavigationController I push three of UITableViewController. In my second UITableViewController I set in viewDidLoad:
self.navigationItem.title = "controller2"
self.navigationItem.backBarButtonItem?.title = "c2"
Then I do the following. Starting at UITableViewController one push UITableViewController two and push UITableViewController three on the UINavigationController. When I reach UITableViewController three the back button displays controller2 instead of c2.
I did the same setup on the first UITableViewController and when I reach UITableViewController two the back button shows the correct title.
Why does the back button shows the wrong title?
As answered Here -
The title of the back button is either:
The title of the previous view controller
The name of the previous view controller's navigation item back button
If you are setting the back button for the current view controller's navigation item you are
not setting the button that get's displayed in the current view. You
are in fact setting the back button that will be used if you push
another view controller from it.
Or
You could init a new back button with title. Put this in the viewDidLoad() of view controller.
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "c2", style: UIBarButtonItemStyle.Bordered, target: nil, action: nil)

iOS Right navigation button does not display in UINavigationBar

I have following view controllers hierarchy:
View Controller VC1
Tab Bar Controller TBC1 - configured in storyboard to lead to a Table View Controller TVC1 and a Map View Controller MVC1
Table View Controller TVC1
Table View Controller TVC2
In VC1, I do this:
[self.navigationController pushViewController:TBC1 animated:YES];
This rightly brings up tab bar controller, with TVC1 in focus.
TVC1 shows back button in its navigation bar (programmatically created from VC1 code), which will get me to VC1, which is expected.
However, from TVC1 onwards, I need one more navigation to TVC2. I am trying to add right button to the TVC1 navigation bar for this, but it doesn't show up.
Here is the code I use in TVC1 (rightButton is UIButton type property of TVC1):
self.rightButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem: UIBarButtonSystemItemAdd
target: self
action: #selector(MySelector:)];
self.rightButton.style = UIBarButtonItemStyleBordered;
self.rightButton.title = #"";
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects: self.rightButton, nil];
(specified blank title and style just to ensure if that's the issue which is causing this, I don't actually need those values)
MySelector is declared in TVC1.h as:
- (void) MySelector:(id)sender;
And it is properly implemented, too.
But rightButton above does not display in TVC1 navigation bar.
What am I missing?
I suspect its with TBC1 (tab bar) that comes between VC1 and TVC1, and somehow it resets navigation properties.
But then I argue that I see navigation bar on TVC1, and a left button leading to VC1.
I checked that in TBC1, self.navigationItem.rightBarButtonItems has 1 object inside which is definitely the rightButton I am adding.
Where am I wrong?
Note: Above is found in all of iOS 5.0, 5.1 and 6.0 simulators.
It seems to me that your are missing UINavigationController between TVC1 and TVC2 in your storyboard. If you are using storyboards then you can create navigation item Add button type on the navigation controller itself and have a PUSH segue to TVC2. See this diagram if that makes sense. If this doesn't solve your problem then please upload example code and I will have a look.
[EDIT]
I had reproduced your issue by creating your view controllers structure in storyboard.
If you notice here TVC1 doesn't have it's UINavigationController but it is inheriting it from VC1. Solution to your problem is rather than adding rightButton onto self add it to self.parentViewController and you will see rightButton in TVC1. But mind you it will also appear in MVC1 as it is belong to TBC1's parent. You can hide right bar button in MVC1's viewWillAppear if you don't want it there. Following is the code.
self.rightButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem: UIBarButtonSystemItemAdd
target: self
action: #selector(MySelector:)];
self.rightButton.style = UIBarButtonItemStyleBordered;
self.parentViewController.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects: self.rightButton,nil];
If you want to Add right button into the TVC1's navigation controller then you need Embed TVC1 into UINavigationController. To do this, select TVC1 screen in the storyboard -> Editor -> Embed In->Navigation Controller. When you do this your code will also work and will show you right button but you will have two navigation controllers(see image below) in it because of your structure of storyboard. You will need to hide Parent's navigation controller in to the TVC1's view did load and have left button to Pop to Parentview Controller. You do the same in MVC1.
Hope this helps! Happy coding :)
Had the same problem recently in Swift and found that embedding the child view in a navigationController was still the correct way to be able to access the rightBarButtonItems.

Resources