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.
Related
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.
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 have two different view controllers. One is programmatically created(slideshow) and the other is with the interface builder(Login page). On the slideshow, once the user reaches the last page, it should perform segue to the login page.
How can I make this work?
First you can't create a segue between a VC created in code and another created in IB ( as both should be in IB ) , you must present it like this
let login = self.storyboard?.instantiateViewController(withIdentifier: "loginID") as! loginViewController
and use
self.present(login, animated: true, completion: nil)
OR use this to completely clear the stack of shown VCs
UIApplication.shared.keyWindow?.rootViewController = login
If two view controller don't need to transmit data, you can just change window root view controller to login page. Of course, with animation would be better.
I am working on an app which needs a menu bar, it should be used in many different views, so here is what i did.
I make a subview which is the menu, it is loaded by other view in Main.storyboard.
Main.storyboard ----- this contains parent view
SimpleCustomView.xib ----- this is the subview
Here is the Problem:
How can I make a button inside of SimpleCustomView which can change the parent view in Main.storyboard? So the users can click on the menu to switch pages.
I have tried:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "PC") as UIViewController
// self.presentViewController(vc, animated: true, completion: nil)
//superview.presentViewController(vc, animated: true, completion: nil)
Neither 3rd line nor 4th line works.
So i got quite confused, how can i do it.
The general approach in a situation such as yours, where you want multiple views to show a certain view from a parent view, would be to send a notification from the child view when the button is clicked. The parent view would be listening for that particular message and then carry out an action - show the menu in this case.
Since I don't know enough about your particular set up, I don't want to hazard providing code which might not really work for you :) If you are able to share your project with us, then I can take a look and give you specific code which should work.
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.