Show and dismiss View Cntrollers in swift 4 - ios

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: {
})

Related

how to dismiss current presenting controller and navigate to other controller using navigation controller?

self.dismiss(animated: false) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.navigationController?.pushViewController(vc, animated: false)
}
self.navigationController will only have a value if your ViewController is embedded in an UINavigationController otherwise it will be nil.
In your case it is nil, so your controller is dismissed successfully but ViewController is not pushed.
In your completion block use self.presentingViewController to push the object.
self.dismiss(animated: false) {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.presentingViewController?.navigationController?.pushViewController(vc, animated: false)
}

Navigate to ViewController and dissmiss VC

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)
})

Attempt to present UIImagePickerController on ViewController whose view is not in the window hierarchy

I'm in trouble, after that I'm moving from View Controller to a second View Controller and then switching back to the View Controller and clicking on the UI Image Picker it's not appearing and bringing me back to the second View Controller. On the debugger it's appearing:
Attempt to present on whose view is not in the window hierarchy!
I'm really becoming crazy. My code that is bringing me back from second View Controller to the first View Controller is inside a button and it's below:
#IBAction func profileButton(_ sender: Any) {
let webVC = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController") as! ViewController
webVC.profileLink = linkProfilo
self.present(webVC, animated: false, completion: nil)
}
in second view controller add this variable:
var firstVC: ViewController?
and this setter function to set it
setup(firstVC: ViewController) {
self.firstVC = firstVC
}
in the first view controller, when presenting second view controller pass in a reference to self (first view controller)by calling the setup function
let secondVC = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as! ViewController
secondVC.setup(firstVC: self)
self.present(secondVC, animated: false, completion: nil)
now when button is clicked in secondVC,
guard let first = self.firstVC else {return}
first.profileLink = linkProfilo
self.dismiss(animated: false, completion: nil)
I finally found the way for fix all of this:
#IBAction func profileButton(_ sender: Any) {
if let webVC = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController") as? ViewController {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
webVC.profileLink = linkProfilo
dismiss(animated: false, completion: nil)
appDelegate.window?.rootViewController!.present(webVC, animated: false, completion: nil)
}
}
it's enough to add the appDelegate sharing method and dismiss before to present the webVC for share the data in the right way and don't cause problems on the first view when presented.

Working with DispatchQueue in swift

I am using dispatcQueue to automatically dismiss my controller but I have an issue is that it dismiss my view controller automatically but also dismiss other view controllers that are presented modally and I want to dismiss only a single view controller
func dismissViewController() {
let pickVc = UIStoryboard(name:"Main", bundle: nil).instantiateViewController(withIdentifier: "request-VC") as! RequestViewController
pickVc.modalPresentationStyle = .custom
pickVc.requestDelegate = self
present(pickVc, animated: true, completion: nil)
}
func openRequestAlertViewController() {
let pickVc = UIStoryboard(name:"Main", bundle: nil).instantiateViewController(withIdentifier: "requestAlertVC") as! RequestAlertViewController
pickVc.modalPresentationStyle = .custom
pickVc.searchDelegate = self
present(pickVc, animated: true, completion: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 20) {
self.dismiss(animated: true, completion: nil)
}
}
func dismissRequestVC() {
let searchVc = UIStoryboard(name:"Main", bundle: nil).instantiateViewController(withIdentifier: "searching-VC") as! SearchingViewController
searchVc.modalPresentationStyle = .custom
present(searchVc, animated: true, completion: nil)
}
but it also dismiss after 20 seconds and I don't want to dismiss this. any help? This is my whole code
Create an instance for a particular viewcontroller which you want to dismiss like the following
var lvc: LoadingViewController?
func showLoadingIn(viewController: UIViewController) {
lvc = LoadingViewController() // create new instance before presentation
viewController.presentViewController(lvc!, animated: false, completion: nil)
}
func dismissLoader() {
lvc?.dismissViewControllerAnimated(true) {
print("Dismissing Loader view Controller")
}
}
You are presenting all viewControllers with the current viewController and while dismissing you are are not dismissing the currently presented viewController. Instead you are dismissing the presenter viewController so all the presented ViewControllers are also getting dismissed.
If you want to dismiss a particular viewController you can do it like this,
yourViewController.dismiss(animated: true, completion: nil)
For example in your case you can do this to dismiss the pickVc after 20 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 20) {
pickVc.dismiss(animated: true, completion: nil)
}

Back to root view controller in swift

Is there any way to dismiss all the view controllers ( in which some controllers are pushed through navigation) and go back to the root view controller. I saw lots of examples but they didn't work in my application. I am using swift 4
This is code in appdelegate
func setNavigationToRootViews(){
storyBoard = UIStoryboard(name: "Main", bundle: nil)
nav = storyBoard?.instantiateViewController(withIdentifier: "mainNavigation") as! UINavigationController?
let accessToken: String? = KeychainWrapper.standard.string(forKey: "token")
print(accessToken as Any)
if accessToken != nil {
let homeVc = storyBoard?.instantiateViewController(withIdentifier: "Home-VC") as! HomeViewController
nav?.pushViewController(homeVc, animated: false)
}else{
let welcomVc = storyBoard?.instantiateViewController(withIdentifier: "login-VC") as! LoginViewController
nav?.pushViewController(welcomVc, animated: false)
}
let leftMenuVC = storyBoard?.instantiateViewController(withIdentifier: "menu-VC") as! MenuViewController
container = MFSideMenuContainerViewController.container(withCenter: nav, leftMenuViewController: leftMenuVC, rightMenuViewController: nil)
container?.panMode = MFSideMenuPanModeNone
window?.rootViewController = container
window?.makeKeyAndVisible()
}
and this in my last View controller
#IBAction func okayBtnTapped(_ sender: Any) {
_ = self.navigationController?.popToRootViewController(animated:
true)
dismiss(animated: true, completion: nil)
}
Try this one:
self.navigationController?.popToRootViewController(animated: true)
You can just set a new RootController like this:
let storyboard = UIStoryboard(name: "sName", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "<YOUR ROOT CONTROLLER>")
self.window?.rootViewController = viewController
If you don't have a window at self.window you need to instanciate one based on your AppDelegate.
If you're within a NavigationController you can also use the answer of #Anshul Bhatheja
Check you navigation controller, and view controllers inside that navigation controller. It seems debugging issue.
this method popToRootViewController(animated:) is the method should work
If you are working with simple push navigation controller and you want to go back to root view controller then you simply have to write
_ = self.navigationController?.popToRootViewController(animated: true)
extension UINavigationController {
func popToViewController(ofClass: AnyClass, animated: Bool = true) {
if let vc = viewControllers.filter({$0.isKind(of: ofClass)}).last {
popToViewController(vc, animated: animated)
}
}
func popViewControllers(viewsToPop: Int, animated: Bool = true) {
if viewControllers.count > viewsToPop {
let vc = viewControllers[viewControllers.count - viewsToPop - 1]
popToViewController(vc, animated: animated)
}
}
}
pop to SomeViewController class
navigationController?.popToViewController(ofClass: SomeViewController.self)
pop 2 view controllers
navigationController?.popViewControllers(viewsToPop: 2)

Resources