user9368327
user9368327

Reputation:

showing view controller when app enter foreground but don't know to dismiss this view controller in swift 4

I want to go to the current opened view controller after the user authenticates with the passcode.

this is my code on (EnterForeground) in appDelegate:

     func applicationWillEnterForeground(_ application: UIApplication) {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    let stb = UIStoryboard(name: "Main", bundle: nil)
    let ps = stb.instantiateViewController(withIdentifier: "psID") as! PassC_VC
    let appdelegate = UIApplication.shared.delegate as! AppDelegate
    self.window?.makeKeyAndVisible()
    DispatchQueue.global().async {
        DispatchQueue.main.async {
            ps.modalPresentationStyle = UIModalPresentationStyle.currentContext
            appdelegate.window?.rootViewController = ps
            print("in forground")
        }
    }

}

this code working successfully and show this window but the problem to dismissing this controller and show the currently active view controller that was opened before show passcode View Controller.

this is my PassC_VC.swift code: addition information: I'm not using any UINavigationController or something

on OK button click after entering password

self.dismiss(animated: true, completion: nil)

Upvotes: 1

Views: 1988

Answers (1)

mrc
mrc

Reputation: 521

You can only dismiss controllers you present. You did not present "ps", instead you set is as the window rootViewController. This means that is is the first controller in the screen, so dismissing it doesn't make sense.

To go back to the controller you had before on screen, you could do one of the following:

OPTION 1: VIEW CONTROLLER REFERENCE

hold a reference to that controller in the appDelegate when your app enters foregound:

func applicationWillEnterForeground(_ application: UIApplication) {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    let stb = UIStoryboard(name: "Main", bundle: nil)
    let ps = stb.instantiateViewController(withIdentifier: "psID") as! PassC_VC
    let appdelegate = UIApplication.shared.delegate as! AppDelegate
    self.window?.makeKeyAndVisible()
    DispatchQueue.global().async {
        DispatchQueue.main.async {
            ps.modalPresentationStyle = UIModalPresentationStyle.currentContext

            if let delegate = UIApplication.shared.delegate as? AppDelegate {
                //Storing the reference
                delegate.yourReferenceToPreviousController = delegate.window?.rootViewController

                //Assigning the new controller
                delegate.window?.rootViewController = ps
                print("in forground")
            }
        }
    }

}

and , on "OK button click after entering password" doing:

if let delegate = UIApplication.shared.delegate as? AppDelegate {
    //You can now use your stored reference to reassign the root view controller
    delegate.window?.rootViewController = delegate.yourReferenceToPreviousController
}

OPTION 2: RE-PRESENTING THE PREVIOUS VIEW CONTROLLER

Or you could avoid keeping a reference to the previous controller and re-instantiate it by doing, on "OK button click after entering password":

let previousController = PreviousController() //This is in code but you can initialize it via storyboard
self.present(previousController, animated: true)

OPTION 3: PROPERLY PRESENT/DISMISS YOUR VIEW CONTROLLER

Another approach would be changing the way you show the controller, by actually getting the visibleController and making him present the PassCode controller like this:

You can use this extension to get the visible controller:

extension UIWindow {

    func visibleViewController() -> UIViewController? {
        if let rootViewController: UIViewController = self.rootViewController {
            return UIWindow.getVisibleViewControllerFrom(vc: rootViewController)
        }
        return nil
    }

    private class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {
        if vc.isKind(of: UINavigationController.self) {
            let navigationController = vc as? UINavigationController
            return UIWindow.getVisibleViewControllerFrom(vc: navigationController!.visibleViewController!)
        } else if vc.isKind(of: UITabBarController.self) {
            let tabBarController = vc as? UITabBarController
            return UIWindow.getVisibleViewControllerFrom(vc: tabBarController!.selectedViewController!)
        } else {
            if let presentedViewController = vc.presentedViewController {
                return UIWindow.getVisibleViewControllerFrom(vc: presentedViewController)
            } else {
                return vc
            }
        }
    }
}

Then in the applicationWillEnterForegound:

func applicationWillEnterForeground(_ application: UIApplication) {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    let stb = UIStoryboard(name: "Main", bundle: nil)
    let ps = stb.instantiateViewController(withIdentifier: "psID") as! PassC_VC
    let appdelegate = UIApplication.shared.delegate as! AppDelegate
    self.window?.makeKeyAndVisible()
    DispatchQueue.global().async {
        DispatchQueue.main.async {
            ps.modalPresentationStyle = UIModalPresentationStyle.currentContext

            //You get the controller that is on screen
            let visibleViewController = UIWindow.getVisibleViewControllerFrom(vc: window?.rootViewController!)
            //Then make it present the controller you want
            visibleViewController.present(ps, animated: true)
            print("in forground")
        }
    }

}

This way you are actually presenting the controller so you can:

self.dismiss(animated: true, completion: nil)

Like you wanted to.

Hope it helps.

Upvotes: 1

Related Questions