I have several views. Here's what it looks like: First view is StartViewController (arrow), which opens TabBarController which is owner of two other views - FavoriteViewController and MapViewController. How to close all of them and go back to the StartViewController?
This should work like starting the app from first view.
I found similar question, but unfortunately it doesn't work.
How to go back to the initial ViewController the right way?
1. First dismiss your current viewController by self.CurrentVC.dismiss(animated: true, completion: nil)
2. then, present/show your first or intial viewController present(firstVC,animated: true,completion: nil)
Here CurrentVC is the name for your current viewController and firstVC will be the name of your first viewController that you want to show.
Related
I have three view controllers written programmatically, the first VC is Sign in but if the user forgets the password this will led him to another two view controllers I need to return to the sign in VC directly form the third VC after the user finish the specific procedures.
you could do like this
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
since are both vc to dissmiss it will return to login vc.
every presented viewController has a property called
PD: presentingViewController, is hold as reference to the viewController that is responsable for present it, so 2dn VC has a reference to 1st VC as presentpingviewcontroller, but also 3er VC have a reference to 2dn vc that has a reference to 1st VC so you call the above method chaining two presenting and ending in first VC, so you could present as many VC as you want as long as you know how many have been presented you could return to what ever you want.
You can use navigation controller, push your view controllers to navigation like
self.navigationController?.pushViewController(viewController: vc, animated: true)
and when you need to close all controllers use
self.navigationController?.popToRootViewController(animated: true)
I switch between views in my app with the following code:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
settingsVC = storyBoard.instantiateViewController(withIdentifier: "SettingsVC") as! SettingsVC
self.present(settingsVC, animated: true, completion: nil)
This works fine, for instance from a main menu, after a press of a button. But I did this a few times after each other going back and forward from the menu to the settings view and I noticed that the view loads as many times as I went back and forward. So it probably creates the view controller again and again. How can I make sure it does in only once. So is there a way to check whether the view controller does exist. As a sidenote: I do not work with a navigation controller, just a few plain viewcontrollers.
Thanks in advance!
So is there a way to check whether the view controller does exist.
It doesn't exist. You yourself create it here, so you know it is created. But it is also destroyed when the opposite happens, i.e. when the view controller you present with present is dismissed. That is expected and correct. If you want state to be preserved between instantiations and restored on the next instantiation, it is up to you to preserve and restore it.
You have a few options. I, like Ayaz, recommend doing this in a navigation controller but if for some reason you don't want to, I would recommend dismissing the SettingsVC when you are done with it. You can do this by calling self.dismiss(animated: true, completion: nil) after hitting the "close" or "back" button.
Please help me with this. I have created a simple project with two views as shown. I have attached the images for my storyboard and swift files. So, I read that viewdidload will be executed only once while loading the view into the memory. But, when I make a transition from secondview to the firstview the viewdidload is executing again and so is the print statement in the viewdidload method.
Someone please explain me this.
viewDidLoad is not called once for the Application. It is get called once for that viewController when the view holds memory and loaded.
So as many number of of time you push to the viewController, that many times it will call the viewDidLoad
viewDidLoad() — Called when the view controller’s content view (the top
of its view hierarchy) is created and loaded
viewWillAppear() — Intended for any operations that you want always to
occur before the view becomes visible.
For more info about this look at the link : https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson4.html
So if the view is already in memory (Like your case), then no need to push again, only need to pop back by this code
self.navigationController?.popViewControllerAnimated(true)
You should not make transition from secondViewController to firstViewController for back. Pop the second view controller by this code to back:
self.navigationController?.popViewControllerAnimated(true)
When you make a transition it makes a new instance from your firstViewController but when you pop the second view controller it dismiss your secondViewController and shows your last viewed viewController again.
Or
in the case that you are not using navigationController you should use below code to dismiss your secondViewController
self.dismissViewControllerAnimated(true, completion: {});
The main point is that you should not use new transition for back.
The simplest way:
1.First embed your ViewController in NavigationController
2.Call to this (instead of create segue for backing)
navigationController?.popToRootViewController(animated: true)
viewDidLoad will be called only once
I know this is probably an easy task but I can't get my head around how to solve it. I'm not using a NavigationController by the way. Basically I have 3 view controllers in my app:
-LoginVC (this has a register button. when tapped, it goes to the SignupVC)
-SignupVC (if user signs up, it will push to the MainAppVC)
-MainAppVC (has a logout button)
For the transitions, I use the method: present(viewController, animated:, completion:)
When the user logs in via the LoginVC, he'll be presented the MainAppVC as expected. When he logs out, I'll dismiss the current VC (which is the MainAppVC) to send him back to the LoginVC.
Now here is the case where I have questions about. When the user does not have an account and signs up, this is the VCs he will pass through (LoginVC > SignupVC > MainAppVC). Once he registers successfully, he'll be presented the MainAppVC. Now once he logs out, he'll be transitioned from the MainAppVC to the SignupVC because I used the same dismiss method.
What I want to do is to send the user back to the LoginVC from the MainAppVC. How do I accomplish that without using a navigation controller in my project? How do popular apps (Facebook, Twitter, Instagram, etc) handle this in their apps?
One way I can think of is to perform a segue from 3rd to 1st VC but I think that's a dirty way since it just adds to the stack, instead of popping it off which is a potential issue.
There are three solutions.
1.Use window root view controller.Set root view controller between login and main view controller.
let loginSb = UIStoryboard(name: "Login", bundle: nil)
let loginVc = loginSb.instantiateInitialViewController()
window!.rootViewController = loginVc
2.Dismiss the sign up view controller the first time you present main view controller.And present the main view controller from login view controller.
3.Try to dismiss the sign up view controller in the completion block when you dismiss the main view controller.
I think the first one is best.
If are forced to NOT use a rootViewController (with UINavigationController), you should check in MainAppVC which one is the previous VC (Pseudocode in the example) and do:
Note: Swift 3 Code.
// If previous VC is LoginVC
dismiss(animated: true)
// else if previous VC is SignupVC
// here's what you want
presentingViewController?.presentingViewController?.dismiss(animated: true)
Hope that helped.
Another option is to use unwind segues.
In the ViewController that you want to go back to, implement a method as follows
#IBAction func unwindToLogin(segue: UIStoryboardSegue) {
}
Then in Storyboard, from the last ViewController right click and drag from the button (for example) to Exit and choose unwindToLoginWithSegue.
Note that you can also do this programatically. Here is a good tutorial.
Best approach is :
Dismiss SignUpVC once User Register successfully, Then from LoginVC present MainVC.
In SignupVC :
self.dismissViewControllerAnimated(true, completion: {
self.LoginVC!.present(MainVC, animated: true, completion:nil)
})
This approach is used mostly.
I created a little game (not with Sprite Kit), I have a MenuViewController and a GameViewController.
On my GameViewController, I have a button "MENU" to go to the menu. I had this code to the GameViewController :
print("test")
It is executed every seconds with using a timer.
When I press the "MENU" button, I find myself on the menu but the timer is still running. I think the GameViewController is not completely removed, how can I do this ?
PS: to dismiss the GameViewController, I use this :
func goToMenuViewController() {
let menuViewController = MenuViewController()
menuViewController.modalTransitionStyle = UIModalTransitionStyle.CrossDissolve
self.presentViewController(menuViewController, animated: true, completion: nil)
}
EDIT 1
I add some infos about my app hierarchy :
When the user launch the app, he finds himself on the MenuViewController.
There is a play button on this ViewController which takes to the GameViewController.
On the MenuViewController, there is an other button which takes to the RulesEditorViewController, allowing to modify rules displayed on the GameViewController
you can not see if the GameViewController is removed in this way.
if you use a timer in a GameViewController, it will keep a ref to GameViewController until it stop executing.
By the way, present menu view controller won't make the game view controller be removed
Your try to dismiss GameViewController is wrong. You are create new Menu controller and showing it above the GameViewController. That's why this controller is still in app memory.
You have to use this function self.dismissViewControllerAnimated(true, completion: nil) or self.navigationController?.popToRootViewControllerAnimated(true) depending on your segue type.
For now if you want access RulesEditorViewController you have to stop the game and leave this controller. But if you want modify options while playing then it will be better if you will access RulesEditorViewController directly from your GameViewController like you trying to show Menu now.
Update:
First of all you should understand view controllers hierarchy and ways how to present it. I believe this tutorial on example of storyboards will help you: http://www.raywenderlich.com/50308/storyboards-tutorial-in-ios-7-part-1