Raymond Led Carasco
Raymond Led Carasco

Reputation: 239

How to present Lock_ViewController when app is entering foreground in SWIFT?

Please help me. I have an app that has a passcode lock feature, this gets activated everytime the user opens the app. If the user goes to home ( app goes to background) and then go back to the app ( foreground) I want to display the lock screen again ( or use other viewcontroller ). How am I going to do this?

I know about the WillEnterForeground in appDelegate, I just can't figure out how am I going to tell my app to present the lock screen instead of the screen it had prior to going to background.

This app is very similar to the photo vault application. Photos are guarded with lock screen and user gets asked the passcode everytime he opens the app

Thank you so much in advance

Upvotes: 1

Views: 6962

Answers (3)

DS.
DS.

Reputation: 3004

Addition to the answer

Swift 4 (with extension)

In your app delegate -

// Show the pin view controller when app becomes active
func applicationDidBecomeActive(_ application: UIApplication) {

    if shouldAskForPin {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let loginVC = storyboard.instantiateViewController(withIdentifier: "PinViewController")
        let topVC = self.window?.rootViewController?.topViewController()
        topVC!.present(loginVC, animated: true, completion: nil)
    }
}

If the app goes to background while pin view is showing, when the app becomes active again, the pin view controller will be added again on top of it and so on. So remove it when resigning. Make sure your restoration identifier is set in the storyboard (or through code) for the PIN View Controller.

func applicationWillResignActive(_ application: UIApplication) {
    if shouldAskForPin {
        let topVC = self.window?.rootViewController?.topViewController()
        if topVC!.restorationIdentifier == "PinViewController" {
            topVC!.dismiss(animated: false, completion: nil)
        }
    }
}

And finally, the extension that makes it work based on the answers above. Usually good to put in a separate file e.g. UIViewController+Extension.swift

import UIKit

extension UIViewController {

    func topViewController() -> UIViewController! {
        if self.isKind(of: UITabBarController.self) {
            let tabbarController =  self as! UITabBarController
            return tabbarController.selectedViewController!.topViewController()
        } else if (self.isKind(of: UINavigationController.self)) {
            let navigationController = self as! UINavigationController
            return navigationController.visibleViewController!.topViewController()
        } else if ((self.presentedViewController) != nil){
            let controller = self.presentedViewController
            return controller!.topViewController()
        } else {
            return self
        }
    }

}

Upvotes: 1

Den
Den

Reputation: 11

Addition to the answer

swift 3.0:

func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController! {

    if rootViewController is UITabBarController {
        let tabbarController =  rootViewController as! UITabBarController
        return self.topViewControllerWithRootViewController(rootViewController: tabbarController.selectedViewController)
    } else if rootViewController is UINavigationController {
        let navigationController = rootViewController as! UINavigationController
        return self.topViewControllerWithRootViewController(rootViewController: navigationController.visibleViewController)
    } else if ((rootViewController.presentedViewController) != nil){
        let controller = rootViewController.presentedViewController
        return self.topViewControllerWithRootViewController(rootViewController: controller)
    } else {
        return rootViewController
    }

}

Usage:

let topController = self.topViewControllerWithRootViewController(rootViewController: UIApplication.shared.delegate?.window??.rootViewController)

Upvotes: 1

Raheel Sadiq
Raheel Sadiq

Reputation: 9867

There are a couple of libraries available

https://github.com/antiraum/THPinViewController

https://github.com/D-32/DMPasscode

https://github.com/tiny2n/JKLLockScreenViewController

If you wish to do it yourself or in middle of implenting it, get the top most controller in willEnterForground method, present your lock screen controller on that controller, on successful pin checking dismiss your lock screen controller, and if you need to notify others, push a notificiation This is how you can get the top most controller

- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
     if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
     } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
     } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
     } else {
        return rootViewController;
    }
}

Swift

func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController! {

    if rootViewController.isKindOfClass(UITabBarController) {
        let tabbarController =  rootViewController as! UITabBarController
        return self.topViewControllerWithRootViewController(tabbarController.selectedViewController)
    }else if (rootViewController.isKindOfClass(UINavigationController)) {
        let navigationController = rootViewController as! UINavigationController
        return self.topViewControllerWithRootViewController(navigationController.visibleViewController)
    }else if ((rootViewController.presentedViewController) != nil){
        let controller = rootViewController.presentedViewController
        return self.topViewControllerWithRootViewController(controller)
    }else {
        return rootViewController
    }

}

Usage

    let topController = self.topViewControllerWithRootViewController(UIApplication.sharedApplication().delegate?.window??.rootViewController)

Modifiy and make an extension or use it as you wish

Upvotes: 8

Related Questions