Reputation: 239
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
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
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
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