I have a game menu with button start game:
#IBAction func startGame(_ sender: AnyObject) {
if let vc = self.storyboard?.instantiateViewController(withIdentifier: "gameViewController") as? GameViewController {
vc.modalTransitionStyle = .crossDissolve
self.present(vc, animated: true, completion: nil)
}
}
Game over code:
if lifes == 0 {
if let vc = self.storyboard?.instantiateViewController(withIdentifier: "mainMenuViewController") as? MainMenuViewController {
vc.modalTransitionStyle = .crossDissolve
self.present(vc, animated: true, completion: nil)
}
}
When user click on button i show new view controller with Sprite Kit scene. But when game is over i go back to menu. And if we click Start game again, fps falls from 60(in my case) to 30, then if again to 20 etc. Seems like old view controller still working. How to dismiss it ?
I read similar questions, but didn't find answer in them.
Ok, now your issue is clear.
You should not present a new MainViewController when game is over. This will lead you to potentially infinite stack of view controllers like this:
Main -> Game -> Main -> Game -> ...
Instead you should dismiss your Game vc and return to the previous controller, so that you will always have one or two controllers in memory.
So you should replace this:
if lifes == 0 {
if let vc = self.storyboard?.instantiateViewController(withIdentifier: "mainMenuViewController") as? MainMenuViewController {
vc.modalTransitionStyle = .crossDissolve
self.present(vc, animated: true, completion: nil)
}
}
With this:
if lifes == 0 {
dismiss(animated: true, completion: nil) //will bring you to previous Main vc
}
Edit:
If you have more than two controllers to show, you should consider navigation controller approach. Basically you create it with rootViewController (MainVC), then push GameVC, then push GameOver.
In MainVC:
self.navigationController?.pushViewController(gameVC, animated: true)
In GameVC:
self.navigationController?.pushViewController(gameOverVC, animated: true)
To pop only only one controller:
self.navigationController?.popViewController(animated: true)
To pop to the first controller:
self.navigationController?.popToRootViewController(animated: true)
Related
I'm trying to dismiss viewcontroller presented as modal("Present Modally") and then popViewController in navigationController. Here is my storyboard, I want to go from QRScanner VC to Monitoring VC.
Here is how I'm presenting QRScanner VC in Add Device VC:
let storyboard = UIStoryboard(name: StoryboardIDs.MainStoryboard, bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: VCIDs.QRDeviceScannerVC) as! QRDeviceScannerVC
controller.deviceName = deviceNameTxt.text
present(controller, animated: false, completion: nil)
Here is how I'm trying to go back to MonitoringVC:
self?.navigationController?.popViewController(animated:true)?.navigationController?.popViewController(animated: false)
Also tried:
self?.dismiss(animated: true, completion: {
self?.presentingVC?.navigationController?.popViewController(animated: false)
})
It always goes to the Add Device VC instead of Monitoring VC
Use an unwind segue, with the unwind target method located in the Monitoring VC. All the right stuff will just happen as if by magic.
You can try with
self?.dismiss(animated: false, completion:nil)
self?.presentingVC?.navigationController?.popViewController(animated: true)
Just check if you have reference to the navigation controller
Here i'm dismissing one VC and trying to navigate new VC , but navigation not working. Dismiss VC working fine.
#IBAction func onClickEmailBtn(_ sender: UIButton) {
//dismiss VC
self.dismiss(animated: false, completion: nil)
//Navigate to VC
DispatchQueue.main.async {
let cevc = self.storyboard?.instantiateViewController(withIdentifier: "CEVC") as! EmailViewController
self.navigationController?.pushViewController(cevc, animated: true)
}
}
Here I have one NavigationViewController called VC1, on that I'm presenting one VC called VC2. In this VC2 when I click button I want to navigate new VC called EmailVC.
try this code
#IBAction func onClickEmailBtn(_ sender: UIButton) {
if let controller = self.storyboard?.instantiateViewController(withIdentifier: "CEVC") as! EmailViewController {
self.dismiss(animated: false, completion: nil)
self.presentingViewController?.present(controller, animated: true, completion: nil)
}
}
You were trying to push a ViewVontroller from dismissing view controller,
and the answer which you have accepted is presenting a viewController from dismissing viewController. Although it may serve your purpose, but I am going to answer you original question
// get the object of presenting nanvigation controller(navigation controller with has presented this view controller)
let presentingNavigationController = presentingViewController?.navigationController
dismiss(animated: true) {
let cevc = self.storyboard?.instantiateViewController(withIdentifier: "CEVC") as! EmailViewController
// here you push your view controller with presentingNavigationController
presentingNavigationController?.pushViewController(cevc, animated: true)
}
Try to find out Navigation controller using below code and replace Viewcontroller with your Controller name.
let productVC = SeconViewViewController()
let parentVC = (parent!.presentingViewController as! ViewController).childViewControllers.first as! UINavigationController
self.navigationController?.dismiss(animated: true, completion: {
parentVC.pushViewController(productVC, animated: true)
})
I have a Feedback View Controller that is accessed in 7 locations across 4 different screens.
One way it's presented in a navigationController via pushViewController. The other 6 times it's presented modally.
Here's the function that opens the Feedback VC's
struct Constants{
static func openFeedback(openFrom: UIViewController, nav:Bool) {
let fbStoryboard = UIStoryboard(name: "FeedbackViewController", bundle: nil)
let fbVC = fbStoryboard.instantiateViewController(withIdentifier: "FBSBID")
fbVC.modalPresentationStyle = .overFullScreen
fbVC.modalTransitionStyle = .crossDissolve
if nav {
openFrom.navigationController?.pushViewController(fbVC, animated: true)
} else {
openFrom.present(fbVC, animated: true, completion: nil)
}
}
}
The Feedback VC is called with either Constants.openFeedback(openFrom: self, nav: true) or Constants.openFeedback(openFrom: self, nav: false)
Opening the VC works just fine!
Here's my close button on the Feedback View Controller:
#IBAction func closeButtonPressed(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
Which works 6 out of the 7 times, when not in the navigation stack. When it's in the navigation stack, the close button does not do anything.
My question is, how do I close out of the Feedback View Controller, based on if it's in the navigationController stack or not?
You can simply check if view controller is embedded inside UINavigationController by checking if controller's navigationController is nil or not.
So if it is embedded you can use popViewController(animated:) on navigation controller to "dismiss" pushed controller
if let navCon = navigationController {
navCon.popViewController(animated: true)
} else {
dismiss(animated: true)
}
When I click on cancel button in a modal pop-up ViewController, for some reason it goes to the very beginning of the navigation stack, instead of back to thew viewController that called it. Am I doing something wrong?
Root of the stack, calling ViewControllerA:
class RootViewController {
let viewController = ViewControllerA(contact: selectedContact)
self.navigationController!.pushViewController(viewController, animated: true)
}
ViewControllerA / Calling the modal:
let viewController = ViewControllerB()
let navigationController = UINavigationController(rootViewController: viewController)
self.present(navigationController, animated: true, completion: nil)
ViewControllerB / Dismissing the modal:
#objc func cancelButtonPressed() {
self.dismiss(animated: true, completion: nil)
}
I'm trying to present a view controller and dismiss my current modal view. I saw the answers on StackOverflow, but I don't understand it.
self.dismissViewControllerAnimated(true, completion: {
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("myViewController")
self.presentViewController(vc!, animated: true, completion: nil)
})
Could anyone please tell me, how to do it simply? Thanks
Check your main controller in stack and pop all other view controllers and then present new View Controller.
if let controllers = self.navigationController?.viewControllers {
for vc in controllers {
// Check if the view controller is of MainViewController type
if let myVC = vc as? MainViewController {
self.navigationController?.popToViewController(myVC, animated: false)
}
}
}
Push view controller :
let secondVC = self.storyboard?.instantiateViewController(withIdentifier: "secondVC") as! SecondViewController
self.navigationController?.pushViewController(secondVC, animated: true)
or Present View Controller :
let next = self.storyboard?.instantiateViewController(withIdentifier: "secondVC") as! SecondViewController
self.present(next as UIViewController, animated: true, completion: nil)
You can use this code to Present viewcontroller.
let yourVC = UIStoryboard(name: storyBord, bundle: nil).instantiateViewController(withIdentifier:ID) as! yourViewController
let navController = UINavigationController(rootViewController: yourVC)
self.present(navController, animated: true, completion: {
})
And for dissmissing use this in your presented viewController
self.dismiss(animated: true, completion: {
})