I have an application with a navigation bar that pushes to a login screen view controller and then pushes to a main menu. Is there any way I can remove the back button off the main menu, so the user is unable to go back to the login screen?
Thanks!
EDIT: Using Xcode 4.3 and doing all the leg work programmatically.
You can do:
[self.navigationItem setHidesBackButton:YES];
In your second view controller (the one you want to hide the button in).
Peters answer is correct, although I think the better question is why? In a schema like yours where you are wanting to login a user, instead of using a Pushed VC, present a Modal VC and use a delegate method to get back the userinfo that was obtained in the Login process. I can post a complete code example if you need it, but it sounds like you have the details worked out with your login process. Just use:
presentModalViewController
instead of:
pushViewController
That way, you don't have to worry about the navigation stack and doing something that isn't really in-line with the user interface guidelines.
In swift
self.navigationItem.hidesBackButton = true
The above code did not work for me. As suggested in UINavigationItem setHidesBackButton:YES won't prevent from going back,
I had to use:
[self.navigationItem setLeftBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:[[UIView alloc] init]]];
Try this:
[self.navigationItem setHidesBackButton:YES];
Or
[self.navigationItem setHidesBackButton:YES animated:YES];
Tried in Xcode7.3.1, swift
self.navigationItem.setHidesBackButton(true, animated: true)
It only hide the back arrow and disabled the back action, but I can still see the name of the previous view controller.
For those who want to also hide the name of the previous view controller, try Yoga's answer works for me. In swift
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIView())
In the case you need to toggle show/hide the back button:
navigationItem.hidesBackButton = true/false
And keep the swipe back gesture:
extension YourViewController: UIGestureRecognizerDelegate {}
And
navigationController?.interactivePopGestureRecognizer?.isEnabled = true
navigationController?.interactivePopGestureRecognizer?.delegate = self
Related
On my side menu I call a NavigationController for each item on didSelectRowAtIndexPath.
Because of that I have a few NavigationControllers. So I created a custom UINavigationController to reuse the code.
The thing is that my UINavigationController subclass is being called but nothing appears on the simulator.
[self.sideMenuViewController setContentViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"EventsXib"]];
EventsXib is my CustomNavigationController
Any idea?
For the record, the whole point for me to do this is that I want the same leftBarButtonItem and 2 rightBarButtonItems on all my ViewControllers.
UPDATED:
I noticed that this actually worked:
self.navigationItem.leftBarButtonItem = self.navigationController.navigationItem.leftBarButtonItem;
self.navigationItem.rightBarButtonItems = self.navigationController.navigationItem.rightBarButtonItems;
But I still have to do this in every viewController, and thats not what I want.
Here is a general idea of what it looks like:
As #GoGreen suggested, I created a base view controller with the corresponding buttons on the navigationItem.
Its not the simple solution I had in my mind but it works pretty good.
In my current app, I have three UIViewControllers and I am using StoryBoard:
ViewController, MenuViewController, CategoriasListViewController.
To show MenuViewController from ViewController, I am using a button action.
To go back from MenuViewController to ViewControler, I am using a BarButton item with the following action method:
- (IBAction)backButton:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
To show CategoriasListViewController from MenuViewController, I am using also a button action.
To go back from CategoriasListViewController to MenuViewControler, I am using a BarButton item with the following action method (the same as above):
- (IBAction)backButton:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
But in this case, MenuViewController is not shown, the BarButton action is ignored.
I am using the customised BarButton actions instead the default Back button, because in the header background I have an image with a logo that would be overlapped by the default Back button.
Any help is welcome. Thank you.
UPDATE 1: This is my StoryBoard:
I have difficulties reading your story board but I'm pretty sure that if you put a break point in your method - (IBAction)backButton:(id)sender you will hit that break point.
I'm pretty sure the method is being call when you hit the button (unless you forgot to hook it).
The problem look like you are wrapping your CategoriasListViewController inside a Brand NEW Navigation controller. So when -backButton: get call you are talking to that new NavigationController instead of the original one that you really want to talk to.
Remove that second unnecessary UINavigationController and it should work.
I have the following code:
NSArray* stack = self.navigationController.viewControllers;
NSArray* newStack = #[stack[0], stack[2]];
[self.navigationController setViewControllers:newStack animated:NO];
stack contains 3 view controllers. The problem is that the navigation bar is not removing UINavigationItems to match, so self.navigationController.navigationBar.items.count still returns 3 after running this code. Going back gets you into a weird state where you have a back button at the top that you can press but it just disappears, not taking you back any further.
Is this a bug in iOS 7 or am I just trying to do something really stupid? What's the best way to fix or work around this?
The navigationBar has its own ‘items’ stack which is not updated until viewDidAppear hits.
Which means, if we recreate the navigation controllers’ stack in viewDidLoad using i.e. setViewControllers: when we get to viewDidAppear we will have the current item added to the bars’ ‘items’ stack and therefore the UINavController viewController stack will not be in sync with the UINavBar items stack. This appears to be an iOS 7 bug.
In iOS 6.0 the 2 different stacks do not get out of sync no matter where we set the new viewControllers stack.
So try moving your code in viewDidAppear and see if that fixes the problem. I bet it will, because for me it did.
The behavior you are describing is a corrupt navigation controller stack. This is probably because you are trying to use a navigationController improperly. I don't have much context from the code here, but I am guessing you are trying to skip back to your root view controller? I think this is probably more what you would need:
https://developer.apple.com/library/ios/documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html#//apple_ref/occ/instm/UINavigationController/popToRootViewControllerAnimated:
you will then want to add a custom back button with something like so:
UIBarButtonItem* backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(yourMethodToPopToRoot)];
//yourMethodToPopToRoot is a method you create that runs popToRootViewController
self.navigationItem.leftBarButtonItem = backButton;
Any questions let me know.
I have a UIViewController classes A and B. A loads B using: [A.view addSubView B.view].
B has a navigation bar with a Back button. I want to go back to A when I click it, so in the selector I tried [self.view removeFromSuperview], but it only removed the navigation bar. Then I tried [self.view.superview removeFromSuperview], it still just removed the navigation bar. What should I do?
Also, another minor issue with the Back button: setting it's title. I tried these two ways, but it still displays "Back".
navItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Chapter" style:UIBarButtonItemStylePlain target:self action:#selector(handleBackBarButtonItem:)];
navItem.backBarButtonItem.title = #"Chapter";
Thank you in advance!
I don't think you quite understand how navigation (with UINavigationController) works in iOS. Assuming you want animation, this is what you want:
Set up a UINavigationController. This can be done in the app's delegate (to avoid memory leakage, set an instance variable on UINavigationController *navController:
navController = [[UINavigationController alloc] initWithRootViewController:A];
Note that we are adding A as our root view controller.
Push the second view controller when needed. I assume that you are adding B.view after a button is clicked or something. In the implementation of the method that adds the second view controller, run the following code, instead of [A.view addSubview:B.view]. This method should be in the first controller's .m file:
[self.navigationController pushViewController:B animated:YES];
This will also give a nice transition effect.
Pop the second view controller off the stack. With UINavigationController, a pretty arrow-shaped back button is automatically included in a pushed view controller, to navigate back to the last view controller. This means that you don't even need any code to allow backward navigation.
That's it! Now if you need to change the title of B's back button, do this in A's viewDidLoad method:
self.navigationItem.backBarButtonItem = customBackButtonItem;
You can get an array of subviews and then remove the ones you wanted to be removed. This SO post will show you how to remove all subviews or multiple subviews using subviews array.
I am an iOS development newbie. I am using the following code to set my backBarButtonItem -
UIBarButtonItem *temporaryBarButtonItem=[[UIBarButtonItem alloc] init];
temporaryBarButtonItem.title=#"Back";
self.navigationItem.backBarButtonItem = temporaryBarButtonItem;
[temporaryBarButtonItem release];
I also want it to execute another function, apart from going back. Is that possible? Or do I need another button to save?
You can practically do that in your viewDidDisappear or viewWillDisappear method.
If this view can only go back and doesn't present any views, then this should work.
However, if you plan on presenting a subview, modal view, go deeper in the navigation hierarchy, or do other view operations that will cause viewDidDisapper to get called, then you'll need to separate your back-button code logic somehow.
For instance if you will present a modal view from this view, you can check if self.modalViewController is nil, if it is then you have no modal view being present and can safely execute the back-button code. If it is not nil then you have a modal view present and should not execute back-button code. (viewWillDisappear should register the modal view controller as not-nil).
Very simple, try this!
[[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(myCoolAction:)];
Then all you do is change myCoolAction: to an appropriate method in your view controller and handle it. Enjoy!
EDIT: Oh, if you want to use this for the backBarButtonItem, it won't work how you expect. The system will not call your target/actions for the backBarButtonItem. They get cleared once assigned to the backBarButtonItem.
One way to handle this is too hook up the your UINavigationController as a delegate. Then in your
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
Method you can do some custom behavior there.
Strictly speaking, this cannot be done with UIKit.
See the docs on backBarButtonItem:
The target and action of the back bar button item you set should be
nil. The default value is a bar button item displaying the navigation
item’s title.
The work around is to specify a leftBarButtonItem and attach whatever custom behaviour you require by attaching a #selector target.
The tricky bit is the button's image itself. As you know the default is not a rectangular button. Rather it has a left side arrow shape. For this you'll need to set a custom image to make the button appear to be the default.
There's tons of resources to do that out there including this one to extract all the UIKit artwork:
https://github.com/0xced/UIKit-Artwork-Extractor
You can add UIBarButtonItem in xib and add handler event there.
Else create UIBarButtonItem with a custom view, which is an UIButton and add event handler.
You should be able to do something like this instead of using viewDidDisappear or viewWillDisappear.
Place this in viewDidLoad:
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleDone target:self action:#selector(cancelButtonAction:)];
self.navigationItem.leftItemsSupplementBackButton = NO;
Then you can create the method cancelButtonAction cancelButtonAction for your custom code and the back functionality like this:
- (void)cancelButtonAction:(id)sender {
//Your custom code goes here...
//This will perform the back functionality if using a Navigation Controller
[self.navigationController popViewControllerAnimated:YES];
}
Note: this will end up using a rectangular button, without the arrow.