Custom back bar item button - ios

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).

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.

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.

Reference the back button on UINavigationBar

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";

ENSideSwiftMenu: how to use same Navigation Bar for all View Controllers

I am using Evgeny Nazarov's Swift Side Menu for my iOS app and was wondering if anyone has used this same library and able to have the same Navigation Bar for every View Controller that is called from the menu.
I put a BarButtonItem that toggles the sliding menu on my Root View Controller. My problem is that only my Root View Controller shows this Toggle Button. But I would like to have that same Navigation Bar with the Toggle button on every View Controller that is accessible when clicking an option on the sliding menu.
Has anyone had an experience achieving this? Thanks!
UPDATE 1
This is what happens when I added a NavigationBar and BarButtonItem to the other ViewControllers that aren't the RootViewController. The new Navigation Bar ends up under the existing Navigation Bar from the Navigation Controller.
The screen on the left is the Root View Controller and the one on the right is the View Controller when I select the second item on the menu.
UPDATE 2: SOLVED
override func viewDidLoad() {
super.viewDidLoad()
let menuItem = UIBarButtonItem(image: UIImage(named: "icon_menu"), style: .Plain, target: self, action: "menuBarButtonItemClicked")
menuItem.tintColor = UIColor.whiteColor()
self.navigationItem.leftBarButtonItem = menuItem
}
func menuBarButtonItemClicked() {
toggleSideMenuView()
}
You need to put a UIBarButtonItem on the navigation bar in every view controller, not in the root view controller.
I too have used the same design for my app and I solved it this way:
View every sect "Show the Attribute Inspector -> Top bar" the voice "Translucent Navigation Bar", then drag the "Navigation Item" and then "Bar Button Item" in the position you want. Of course every button should have its code or references to the ViewController.
Let me know if you have solved.

How can i navigate to mainviewcontroller from subview

I have just started working with swift, i have created a subview which has a button on it, i would like to use that button to take me to my mainviewcontroller.
i have used same functionality for a different button however having a function in same file allows that button to work the code is below
var playAgainButton = UIButton(frame: CGRectMake(0, 150, 320, 40))
playAgainButton.setTitle("Play Again", forState: UIControlState.Normal)
playAgainButton.addTarget(self, action: Selector("startGame"), forControlEvents: UIControlEvents.TouchUpInside)
playAgainButton.backgroundColor = UIColor.redColor()
gameOver.addSubview(playAgainButton)
is it possible to use similar code to navigate to a different viewcontroller?
Thanks
Are you using storyboards, or is this all in code? If it's in code, create a method like
func goToMainVC() {
if let navController = self.navigationController {
navController.popToRootViewControllerAnimated(true)
}
}
and set the button's target to a selector that calls it.
If you're using storyboards, you have three options:
ctrl+drag a connection from your button back to the main view controller (easy, but bad form because it just pushes the main VC back onto the nav controller);
Add #IBAction before the fun goToMainVC() method above, then ctrl+drag a connection from your button to the view controller in which it's contained, and then select that outlet method (this is how most people would do it); or
The best option is to use an unwind segue, as described here.

Resources