I'm developing an app where the user can buy some food on the app and get delivered at home.
At some point the user's got some products on his cart (displayed in a tab view controller) and he goes to confirm his address and payment method (these are made in two different pushed view controllers). And when the purchase is done, the app displays some message informing if the payment was successful or not (also displayed in a pushed view controller after he confirms the ).
So, after the user complete the purchase I want to dismiss all those view controllers from the purchase process and go back to the tab view controller by tap on a button.
How do I dismiss all those pushed view controllers?
Here is a image of the storyboard:
You can use the navigation controller's built in functionality to pop back to the root view controller.
self.navigationController?.popToRootViewControllerAnimated(true)
This will remove all of the pushed view controllers you have on the navigation stack and return to the base controller on the stack. You can attach this functionality to the action selector for when a button is pressed.
Yes you can do that by the following.
Suppose you have a structure like this ---
Navigation Controller --(root)->VCa-->VCb-->VCc-->VCd
Now you are at VCd and you want to dismiss or rather pop to VCa, then simply do this[self.navigationController popToRootViewController]
This will pop or dismiss all VC and return to VCa, as because VCa is the root view controller of the Navigation Controller.
Now if you want to dismiss or Pop to VCb, then do the following
for(UIViewController *vc in self.navigationController.viewControllers){
if([vc isKindOfClass:[VCb class]]){
// this means you have successfully picked VCb among all the vc
// inside of the viewControllers in the Navigation stack.
[self.navigationController popToViewController:vc animated:YES];
}
}
This should do it. Hope this helps.
Related
Setting:
The first view controller for my app is PostsViewController. In viewDidLoad I check if the user is logged in, and if not I preset SignupVC modally. There is an option to login instead of signup of course, and I want to replace the signup VC with a login VC.
I tried making a "show detail (replace)" segue from signup to login VC, but that seemed to present login modal on top of signup VC. The problem with it is after the user is logged in, I have two modals to close, and it seems tricky to close both of them at the same time. Ideally, I want to replace the signup VC with the login VC and only close one modal.
Q1. How come the show detail segue works like present modally segue when applied to a modal view controller?
Q2. How can I replace the SignUp View controller with a login View controller?
Right so after rereading your question and your comment it's clear what you're trying to do here.
Q1: Because you can only present a viewController modally on parent / child views that are modally presented. You cannot push a new viewController onto a modally presented viewController. In order to push a viewController you need a UINavigationController in the view hierarchy (Normally the parent / root view)
Q2: You'll need to present it modally from the signupVC.
Example:
//Somewhere in SingupVC
[self presentViewController:LoginVC animated:YES completion:nil];
Edit
To answer your question in the comments:
No there really isn't a way to dismiss both VC's at the same time.
However there are a couple of ways to do it almost:
You can set a boolean flag on SingupVC that LoginVC was presented. That way, when viewWill/Did appear is called on singupVC and the boolean flag is set to YES you can call: [self dismissViewControllerAnimated:NO completion:nil];
And that way both VCs are dismissed. One when the user dismisses LoginVC via the back button and SingupVC via a if statement in one of the view life cycle methods (if loginVCPresent) dismiss view, type of thing.
I have a tab view controller with a navigation controller. In the first tab item I click on a button in a view that pops up a view with animated: YES.
Then when that view is done I hit another button that dismisses it. Like:
[self dismissViewControllerAnimated:NO completion:^{
ProfilesViewController *profile = [[ProfilesViewController alloc] init];
[self.navigationController pushViewController:profile animated:YES];
//SHOW YOUR NEW VIEW CONTROLLER HERE!
}];
But everytime this code runs, it dismisses the view, DOES NOT push the profiles controller, and shows the view from the first tab bar item.
How do I push the ProfilesViewController to the screen with a Back arrow?
If you are using dismissViewControllerAnimated to dismiss that means that the VC is presented modally. As such, it doesn't have a navigation controller (so self.navigationController is nil) and thus it can't push anything into the navigation controller.
You should really add a property to the controller which is a delegate or a completion block which can be used to push the controller from another controller (the one that presents it) to dismiss and push the controller.
A second option is to pass the navigation controller, it's a similar amount of code to using a block but not so good.
A crappy option is to use the parentViewController to find the appropriate navigation controller, but that sucks for many reasons.
I'm developing an iPad App using storyboards. In this app when the user click on "preferences" appear a modal View. One button of this view send the user to another View Controller (but this view has an action bar to go back to his root view controller), but when user taps the action bar back button nothing happen (it's called navigationController popViewControllerAnimated), the user continue in the same view.
Can anyone help me??
Thanks.
UPDATE:
The code to handle the back button:
- (IBAction)btnBackTapped:(id)sender {
[self.navigationController popViewControllerAnimated:YES];
}
I'm using Segue (from storyboard) to call this View Controller:
When the user click on "Meus Favoritos"
They will be redirect to this page:
The segue is with a Modal (from image one to two)...
When you are presenting a View Controller modally, it is likely not within a Navigation Controller, so probably the reference to navigationController in your code is nil, can you check that?
If you are presenting your View Controller modally this will work instead
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
However, if you actually want to use a Navigation Controller, you should embed the View Controller that is presenting the Preferences View Controller in a Navigation Controller and present the Preferences View Controller with a show segue instead of a modal one.
I have a sign in VC that pushes a sign up VC; both are under a Navigation Controller. From the sign up VC I call modaling a UITabBar VC with the whole application content. Inside the UITabBar VC I have another VC with a Sign Out method. My question is: how is the correct way to go back to Sign In VC? In this scenario, if I dismiss the UITabBar VC I return to the sign up VC.
I have drawn a diagram that describes the scenario:
Any help will be appreciated.
Thanks,
Marcos
You can change the state of the UINavigationController which is presenting the modal view before dismissing it. For instance calling
[(UINavigationController *)self.presentingViewController popToRootViewControllerAnimated:NO]
from the modal view controller, will result in your underlying UINavigationController to get back to its root view controller, which - in your specific scenario - will be the Sign In VC, so when you dismiss the modal view, the underlying view controller will be whatever you desire.
Can someone explain to me what is the exact difference between modal and push segue?
I know that when we use push the segue gets added to a stack, so when we keep using push it keeps occupying memory?
Can someone please show me how these two are implemented?
Modal segues can be created by simply ctrl-click and dragging to destination but when I do that with the push my app crashes.
I am pushing from a button to a UINavigationController that has a UIViewController.
A push Segue is adding another VC to the navigation stack. This assumes that VC that originates the push is part of the same navigation controller that the VC that is being added to the stack belongs to. Memory management is not an issue with navigation controllers and a deep stack. As long as you are taking care of objects you might be passing from one VC to another, the runtime will take care of the navigation stack. See the image for a visual indication:
A modal Segue is just one VC presenting another VC modally. The VCs don't have to be part of a navigation controller and the VC being presented modally is generally considered to be a "child" of the presenting (parent) VC. The modally presented VC is usually sans any navigation bars or tab bars. The presenting VC is also responsible for dismissing the modal VC it created and presented.
Swift 3.0 and XCode 8.2.1 update
1. Push Segue
Push segue has been renamed as Show segue. To create push segue, the parent view controller needs to be embedded in navigation controller. The navigation controller provides navigation bar. Once you connect two view controller with push segue, the child view controller will automatically has navigation bar on top. The child view controller will be added on top of the navigation stack.
Push segue also provides default features. The child view controller will have a back button that gets you back to the parent view controller. You can also swipe right to pop the child view controller. The animation for push segue is like sliding pages horizontally.
While you are allowed to make a push segue from a view controller that is not in a navigation controller, you will lose all the features like navigation bar, animation, gesture etc when you do so. In this case, you should embed your parent view controller inside navigation view controller first and then make push segue to child view controllers.
2. Modal Segue
A modal segue (i.e. present modally), on the other hand, is presenting over the current view controller. The child view controller will not inherit navigation view controller so the navigation bar will be lost if you present modal segue from a view controller with navigation view controller. You have to embed the child view controller in navigation controller again and start a brand new navigation stack if you want it back. If you want to get back to parent view controller, you have to implement this by yourself and call dismiss from code.
Animation for modal segue is that the child view controller will comes up from the bottom of the page. The navigation view controller is also gone in this demo
The push view must be built in a navigationController.
Click on your master view, then in the menu bar choose:
EDITOR->embed in->navigationController
This is pushing controls using custom push and segue methods for storyboard
And Modal is way to navigate through views without using Storyboards.