how to dismiss alert view after validation? - ios

I had used SCLAlertView used for forgot password in this i had placed a textfield to enter email so that after making successful validation only it need to hide without this it should not hide can anyone help me how to implement this ?
My code is shown below
#IBAction func forgetPasswordButton(_ sender: Any) {
let appearance = SCLAlertView.SCLAppearance(showCloseButton: true)
let alert = SCLAlertView(appearance: appearance)
let txt = alert.addTextField("Enter your emailid")
_ = alert.addButton("Submit", action: {
let action = txt.text
print(action as Any)
})
if(txt.text?.isEmpty)! == true{
}else{
}
_ = alert.showEdit("Forgot Password", subTitle:"Please enter your email address below.You will receive a link to reset your password",closeButtonTitle: "Cancel")
}

use the property of hideView() and call like
let action = txt.text
print(action as Any)
alert.hideView()
})
for more reference you can get the sample here

Related

How to run Asynchronous function in a Uibutton in swift

I want the getUserToken function and userLogin function to run before the next line which is the Firebase Authentication. For it to run ansynchronous
#IBAction func loginButtonPressed(_ sender: UIButton) {
self.showSpinner(onView: self.view)
guard var phoneNumber = phoneTextField.getRawPhoneNumber() else { return }
phoneNumber = "+234\(phoneNumber)"
guard var userPhoneNumber = phoneTextField.getRawPhoneNumber() else { return }
userPhoneNumber = "234\(userPhoneNumber)"
guard let userName = nameTextField.text else {return}
print(phoneNumber)
getUserAcessToken()
userLogin()
//Validate Required fields are mnot empty
if nameTextField.text == userName {
//Firebase Manipulation
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { (verificationId, error) in
if error == nil {
print(verificationId!)
//UserDefaults Database manipulation for Verification ID
guard let verifyid = verificationId else {return}
self.defaults.set(verifyid, forKey: "verificationId")
self.defaults.synchronize()
self.removeSpinner()
}else {
print("Unable to get secret verification code from Firebase", error?.localizedDescription as Any)
let alert = UIAlertController(title: "Please enter correct email and phone number", message: "\n", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
return
}
}
}
let OTPRequestVC = storyboard?.instantiateViewController(withIdentifier: "OTPRequestViewController") as! OTPRequestViewController
OTPRequestVC.userId = userId
OTPRequestVC.userEmailData = userEmail
self.present(OTPRequestVC, animated: true)
}
I want the two functions to run asynchronously before the firebase auth.
Its not a good idea to run the time consuming functions on the main thread.
My suggestions would be.
getUserAcessToken() and userLogin() functions Should have a callback. Which will make those functions run on a different thread (I believe those functions are making api call which is done in the background thread)
You could call userLogin() in the completion handler of getUserAcessToken() and then firebaseAuth in the completion handler of getUserAcessToken().
This will make sure that the UI is not hanged till you make those api calls and the user will know that something is going on in the app and the app is not hanged.
Without reproducing the entire intended functionality, the pattern you want to follow is:
func loginButtonPressed(_ sender: UIButton) {
// Any immediate changes to the UI here
// ...
// Start time consuming task in background
DispatchQueue.global(qos: .userInitiated).async {
getUserAccessToken()
userLogin()
// Make your Firebase call
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { (verificationId, error) in
// Any response validation here
// ...
DispatchQueue.main.async {
// Any UI updates here
}
}
}
}

siri shortcut button (INUIAddVoiceShortcutButton) shows wrong title when have multiple shortcuts (NSUserActivity)

I've 2 siri shortcuts in my App.
I use NSUserActivity to donate these shortcuts. I've also created 2 NSUserActivityTypes in my info.plist.
There are 2 view controllers which handle these shortcuts (1 view controller for 1 shortcut).
If I add 1 siri shortcut from 1 view controller and then go to 2nd view controller the native siri shortcut button (INUIAddVoiceShortcutButton) on 2nd view controller automatically picks the first shortcut (created from 1st view controller) and shows "Added to Siri" with suggested phrase instead of showing "Add to Siri" button. I double checked that each NSUserActivity has different identifier but still somehow its picks the wrong shortcut.
View Controller 1:
let userActivity = NSUserActivity(activityType: "com.activity.type1")
userActivity.isEligibleForSearch = true
userActivity.isEligibleForPrediction = true
userActivity.title = shortcut.title
userActivity.suggestedInvocationPhrase = suggestedPhrase
let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
attributes.contentDescription = description
userActivity.contentAttributeSet = attributes
let shortcut = INShortcut(userActivity: userActivity)
let siriButton = INUIAddVoiceShortcutButton(style: .whiteOutline)
siriButton.translatesAutoresizingMaskIntoConstraints = false
siriButton.shortcut = shortcut
self.view.addSubview(siriButton)
View Controller 2:
let userActivity2 = NSUserActivity(activityType: "com.activity.type2")
userActivity2.isEligibleForSearch = true
userActivity2.isEligibleForPrediction = true
userActivity2.title = shortcut.title
userActivity2.suggestedInvocationPhrase = suggestedPhrase
let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
attributes.contentDescription = description
userActivity2.contentAttributeSet = attributes
let shortcut = INShortcut(userActivity: userActivity2)
let siriButton = INUIAddVoiceShortcutButton(style: .whiteOutline)
siriButton.translatesAutoresizingMaskIntoConstraints = false
siriButton.shortcut = shortcut
self.view.addSubview(siriButton)
A similar thing happens when I delete the App and reinstall without deleting the shortcuts from Phone's Settings App.
Seems like its an IOS bug. I figured out a workaround for this problem. You have to create a new siri button every time the user add/edit the siri shortcut. Before creating siri button do the following things
1- Get all the voice shortcuts from INVoiceShortcutCenter by calling the function. Note that this happens asynchronously, so you need to do it some time before you need the data (e.g. in your AppDelegate). You'll also need to re-load this whenever the user adds a Siri Shortcut (probably in the INUIAddVoiceShortcutViewControllerDelegate.addVoiceShortcutViewController(_:didFinishWith:error) method).
INVoiceShortcutCenter.shared.getAllVoiceShortcuts { (voiceShortcutsFromCenter, error) in
guard let voiceShortcutsFromCenter = voiceShortcutsFromCenter else {
if let error = error as NSError? {
os_log("Failed to fetch voice shortcuts with error: %#", log: OSLog.default, type: .error, error)
}
return
}
self.voiceShortcuts = voiceShortcutsFromCenter
}
2- In View Controller-1 check if the shortcut is already added or not by iterating all the voice shortcuts
let voiceShorcut = voiceShortcuts.first { (voiceShortcut) -> Bool in
if let activity = voiceShortcut.shortcut.userActivity, activity.activityType == "com.activity.type1" {
return true
}
return false
}
3- If your voice shortcut is registered then pass the INShortcut to siri button otherwise don't set it.
if voiceShorcut != nil {
let shortcut = INShortcut(userActivity: userActivity1)
siriButton.shortcut = shortcut
}
Do the same thing in Second View Controller.
It's iOS 12.0 bug.
You can fix it by update INUIAddVoiceShortcutButton.voiceShortcut with correct value.
Use KVO to observe "voiceShortcut" property and when it change assign correct value to it.
I've moved to intents setup now and I find that even having just one intent setup and working the INUIAddVoiceShortcutButton is not able to track my shortcut. Once phrase is recorded it shows the Added to Siri with phrase.
But every time the app relaunches the Add to Siri button shows up instead of the Added to Siri button with recorded phrase.
I have tried going by Bilal's suggestion and although I can see the INVoiceShortcutCenter showing me my shortcut as present it doesn't loaded it into the Siri button.
My code looks like this for the button itself.
private func addSiriButton() {
let addShortcutButton = INUIAddVoiceShortcutButton(style: .blackOutline)
addShortcutButton.delegate = self
addShortcutButton.shortcut = INShortcut(intent: engine.intent )
addShortcutButton.translatesAutoresizingMaskIntoConstraints = false
siriButtonSubView.addSubview(addShortcutButton)
siriButtonSubView.centerXAnchor.constraint(equalTo: addShortcutButton.centerXAnchor).isActive = true
siriButtonSubView.centerYAnchor.constraint(equalTo: addShortcutButton.centerYAnchor).isActive = true
}
I have all the protocols implement and I had a close look at the Soup app but just can't figure out what drives this inaccuracy.
Funny enough, even British Airways app developers have given up on that as their button has exactly the same fault behaviour.
Update: I've built another test project with minimal amount implementation for the Intent and the Add to Siri and Added to Siri works perfectly. I'm guessing at this point that there is something in my own apps codebase that is causing this unwanted behaviour.
update 2 Just wanted to let everyone know I have fixed the issue. Using intents works fine but there is definitely a little sensitivity in the Intents definition file itself. All I had to do is create a new intent which then was generated and that worked. Seems my initial intent was somehow corrupt but there were no errors. After creating another intent and re-assigning intent handling function to that it all worked as intended. (pun intended)
I encountered this error when I had an existing intent and working configuration, but added a new parameter. However, in my Intent configuration, I had not added the new parameter name to a supported combination under the Shortcuts app section.
For example, if I had two properties myId and myName, and specified them as such:
let intent = MyIntent()
intent.myId = 1234
intent.myName = "banana"
Then I would need a supported combination of myId, myName in my intents definition file. In my particular case, I had forgotten myName so the INUIAddVoiceShortcutButton was attempting to do a lookup using myId, myName but didn't know how.
I just fixed this issue myself by changing my implementation (originally based on the soupchef app) to this code sample provided by apple (https://developer.apple.com/documentation/sirikit/inuiaddvoiceshortcutbutton):
EDIT: I added code that shows how I create and pass in the shortcutObject (INShortcut) for both UserActivity and custom Intent shortcuts.
The Shortcut class is an enum that contains a computed property called intent that returns an instantiation of the custom intent.
private func addShortcutButton(shortcut: Shortcut, parentViewController: UIViewController, shortcutViewControllerDelegate: INUIAddVoiceShortcutViewControllerDelegate) {
guard let view = parentViewController.view else { return }
if let intent = shortcut.intent {
shortcutObject = INShortcut(intent: intent)
} else if let userActivity = view.userActivity {
shortcutObject = INShortcut(userActivity: userActivity)
}
self.shortcutViewControllerDelegate = shortcutViewControllerDelegate
addSiriButton(to: shortcutButtonContainer)
}
func addSiriButton(to view: UIView) {
let button = INUIAddVoiceShortcutButton(style: .whiteOutline)
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
view.centerXAnchor.constraint(equalTo: button.centerXAnchor).isActive = true
view.centerYAnchor.constraint(equalTo: button.centerYAnchor).isActive = true
button.addTarget(self, action: #selector(addToSiri(_:)), for: .touchUpInside)
}
// Present the Add Shortcut view controller after the
// user taps the "Add to Siri" button.
#objc
func addToSiri(_ sender: Any) {
guard let shortcutObject = shortcutObject else { return }
let viewController = INUIAddVoiceShortcutViewController(shortcut: shortcutObject)
viewController.modalPresentationStyle = .formSheet
viewController.delegate = shortcutViewControllerDelegate
parentViewController?.present(viewController, animated: true, completion: nil)
}
So we can't use the default Siri button, you have to use custom UIButton.
The class VoiceShortcutsManager will check all the voice intents and then we can search that list check if exist one match if yes so we should suggest edition if not we should suggest adding.
public class VoiceShortcutsManager {
private var voiceShortcuts: [INVoiceShortcut] = []
public init() {
updateVoiceShortcuts(completion: nil)
}
public func voiceShortcut(for order: DeviceIntent, powerState: State) -> INVoiceShortcut? {
for element in voiceShortcuts {
guard let intent = element.shortcut.intent as? ToggleStateIntent else {
continue
}
let deviceIntent = DeviceIntent(identifier: intent.device?.identifier, display: intent.device?.displayString ?? "")
if(order == deviceIntent && powerState == intent.state) {
return element
}
}
return nil
}
public func updateVoiceShortcuts(completion: (() -> Void)?) {
INVoiceShortcutCenter.shared.getAllVoiceShortcuts { (voiceShortcutsFromCenter, error) in
guard let voiceShortcutsFromCenter = voiceShortcutsFromCenter else {
if let error = error {
print("Failed to fetch voice shortcuts with error: \(error.localizedDescription)")
}
return
}
self.voiceShortcuts = voiceShortcutsFromCenter
if let completion = completion {
completion()
}
}
}
}
And then implement in your ViewController
class SiriAddViewController: ViewController {
let voiceShortcutManager = VoiceShortcutsManager.init()
override func viewDidLoad() {
super.viewDidLoad()
contentView.btnTest.addTarget(self, action: #selector(self.testBtn), for: .touchUpInside)
}
...
#objc func testBtn() {
let deviceIntent = DeviceIntent(identifier: smartPlug.deviceID, display: smartPlug.alias)
//is action already has a shortcut, update shortcut else create shortcut
if let shortcut = voiceShortcutManager.voiceShortcut(for: deviceIntent, powerState: .off) {
let editVoiceShortcutViewController = INUIEditVoiceShortcutViewController(voiceShortcut: shortcut)
editVoiceShortcutViewController.delegate = self
present(editVoiceShortcutViewController, animated: true, completion: nil)
} else if let shortcut = INShortcut(intent: intentTurnOff) {
let addVoiceShortcutVC = INUIAddVoiceShortcutViewController(shortcut: shortcut)
addVoiceShortcutVC.delegate = self
present(addVoiceShortcutVC, animated: true, completion: nil)
}
}
}
#available(iOS 12.0, *)
extension SiriAddViewController: INUIAddVoiceShortcutButtonDelegate {
func present(_ addVoiceShortcutViewController: INUIAddVoiceShortcutViewController, for addVoiceShortcutButton: INUIAddVoiceShortcutButton) {
addVoiceShortcutViewController.delegate = self
addVoiceShortcutViewController.modalPresentationStyle = .formSheet
present(addVoiceShortcutViewController, animated: true, completion: nil)
}
func present(_ editVoiceShortcutViewController: INUIEditVoiceShortcutViewController, for addVoiceShortcutButton: INUIAddVoiceShortcutButton) {
editVoiceShortcutViewController.delegate = self
editVoiceShortcutViewController.modalPresentationStyle = .formSheet
present(editVoiceShortcutViewController, animated: true, completion: nil)
}
}
#available(iOS 12.0, *)
extension SiriAddViewController: INUIAddVoiceShortcutViewControllerDelegate {
func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
voiceShortcutManager.updateVoiceShortcuts(completion: nil)
controller.dismiss(animated: true, completion: nil)
}
func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
controller.dismiss(animated: true, completion: nil)
}
}
#available(iOS 12.0, *)
extension SiriAddViewController: INUIEditVoiceShortcutViewControllerDelegate {
func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didUpdate voiceShortcut: INVoiceShortcut?, error: Error?) {
voiceShortcutManager.updateVoiceShortcuts(completion: nil)
controller.dismiss(animated: true, completion: nil)
}
func editVoiceShortcutViewController(_ controller: INUIEditVoiceShortcutViewController, didDeleteVoiceShortcutWithIdentifier deletedVoiceShortcutIdentifier: UUID) {
voiceShortcutManager.updateVoiceShortcuts(completion: nil)
controller.dismiss(animated: true, completion: nil)
}
func editVoiceShortcutViewControllerDidCancel(_ controller: INUIEditVoiceShortcutViewController) {
voiceShortcutManager.updateVoiceShortcuts(completion: nil)
controller.dismiss(animated: true, completion: nil)
}
}
}
This code was inspired/copy from this webpage:
https://www.nodesagency.com/test-drive-a-siri-shortcuts-intro/
My experience with solving this was a little different. Some intents added via the Add to Siri button worked, which adjusted to "Added to Siri", while others didn't. I realised the actions that worked didn't require parameters.
After setting default values for intents that exposed parameters, which are passed into INShortcut (and then assigned to INUIAddVoiceShortcutButton), all buttons updated their state correctly!

IOS navigationController?.popToRootViewController has wrong

#IBAction func addInformation(_ sender: UIBarButtonItem) {
// check rateHourly has value
if let editedRateHourly = rateHourly.text {
print("editedRateHourly condition is \(editedRateHourly)")
if editedRateHourly != ""{
print("not nil")
// check edit value is number?
let num = Int(editedRateHourly)
if num != nil {
print("is num")
// add to database
UserDefaults.standard.set(editedRateHourly, forKey: "\(findDate())")
UserDefaults.standard.synchronize()
// back to last viewController
navigationController?.popToRootViewController(animated: true)
}else{
print("not num")
print("error alert push!!")
popErrorAlert()
}
}else {
print("nil")
print("editedRateHourly condition is nil")
popErrorAlert()
}
}
}
#IBAction func cannelInformationPage(_ sender: UIBarButtonItem) {
navigationController?.popToRootViewController(animated: true)
}
I want to create a new simple edit page. It's two problem for me that when I finish edition if-else will check the condition is correct or not and then save the data popToRootViewControlle. When I finish edition I click on "addInformation" BarButtonItem and I get UI wrong. the Other wrong is when I click on editField but I don't enter any condition. And then I click on "cannelInformationPage" UIBarButtonItem. It also get wrong.
It's what I get wrong
wrong information
Because it returns Bool
_ = navigationController?.popToRootViewController(animated: true)
_ = self.navigationController?.popViewController(animated: true)
If you want to come back to last view controller than you can try above line, hope its work for you.

How to get user's phone number?

I have just started using Digits - Twitter API for Phone Number verification, but it seems I'm unable to read the user's Phone number, I'm not sure if there is a function for that or so, but after reading a while I knew that I can do that with a Call back after successful phone verification but no explanation for that !
AuthConfig.Builder authConfigBuilder = new AuthConfig.Builder()
.withAuthCallBack(callback)
.withPhoneNumber(phoneNumberOrCountryCodeFromMyActivity)
found this snippet but again not sure where to implement it.
HERE is my Action for the login button with phone verification:
fileprivate func navigateToMainAppScreen() {
performSegue(withIdentifier: "signedIn", sender: self)
}
#IBAction func tapped(_ sender: Any) {
let configuration = DGTAuthenticationConfiguration(accountFields: .defaultOptionMask)
configuration?.appearance = DGTAppearance()
configuration?.appearance.backgroundColor = UIColor.white
configuration?.appearance.accentColor = UIColor.red
// Start the Digits authentication flow with the custom appearance.
Digits.sharedInstance().authenticate(with: nil, configuration:configuration!) { (session, error) in
if session != nil {
// Navigate to the main app screen to select a theme.
self.navigateToMainAppScreen()
} else {
print("Error")
}
}
}
So I found the answer after digging a lot more in Digits Documentations and it was pretty simple, I had to add:
print(session.phoneNumber)
print(session.userID)
In the didTap function, so the complete code will be:
#IBAction func tapped(_ sender: Any) {
let configuration = DGTAuthenticationConfiguration(accountFields: .defaultOptionMask)
configuration?.appearance = DGTAppearance()
configuration?.appearance.backgroundColor = UIColor.white
configuration?.appearance.accentColor = UIColor.red
// Start the Digits authentication flow with the custom appearance.
Digits.sharedInstance().authenticate(with: nil, configuration:configuration!) { (session, error) in
if session != nil {
//Print Data
print(session?.phoneNumber)
print(session?.userID)
// Navigate to the main app screen to select a theme.
self.navigateToMainAppScreen()
} else {
print("Error")
}
}
}
Here is the Reference I have used:
https://docs.fabric.io/apple/examples/cannonball/index.html#sign-in-with-digits

How to handle touchID when loading app from background Swift

I'm implementing the login possibility with touchID using Swift.
Following: when the App is started, there is a login screen and a touchID popup - that's working fine. The problem occurs, when the app is loaded from background: I want the touchID popup appear over a login screen if a specific timespan hasn't been exceeded yet - but this time I want the touchID to go to the last shown view before the app entered background. (i.e. if the user wants to cancel the touchID, there is a login screen underneath where he then can authenticate via password, which leads him to the last shown view OR if the touchID authentication succeeded, the login screen should be dismissed and the last shown view presented.)
I really tried everything on my own, and searched for answers - nothing did help me. Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
//notify when foreground or background have been entered -> in that case there are two methods that will be invoked: willEnterForeground and didEnterBackground
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(self, selector: "willEnterForeground", name:UIApplicationWillEnterForegroundNotification, object: nil)
notificationCenter.addObserver(self, selector: "didEnterBackground", name: UIApplicationDidEnterBackgroundNotification, object: nil)
password.secureTextEntry = true
if (username != nil) {
username.text = "bucketFit"
}
username.delegate = self
password.delegate = self
if let alreadyShown : AnyObject? = def.objectForKey("alreadyShown") {
if (alreadyShown == nil){
authenticateWithTouchID()
}
}
}
willEnterForeground:
func willEnterForeground() {
//save locally that the guide already logged in once and the application is just entering foreground
//the variable alreadyShown is used for presenting the touchID, see viewDidAppear method
def.setObject(true, forKey: "alreadyShown")
if let backgroundEntered : AnyObject? = def.objectForKey("backgroundEntered") {
let startTime = backgroundEntered as! NSDate
//number of seconds the app was in the background
let inactivityDuration = NSDate().timeIntervalSinceDate(startTime)
//if the app was longer than 3 minutes inactiv, ask the guide to input his password
if (inactivityDuration > 2) {
showLoginView()
} else {
def.removeObjectForKey("alreadyShown")
showLoginView()
}
}
}
authenticateWithTouchID():
func authenticateWithTouchID() {
let context : LAContext = LAContext()
context.localizedFallbackTitle = ""
var error : NSError?
let myLocalizedReasonString : NSString = "Authentication is required"
//check whether the iphone has the touchID possibility at all
if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error) {
//if yes then execute the touchID and see whether the finger print matches
context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedReasonString as String, reply: { (success : Bool, evaluationError : NSError?) -> Void in
//touchID succeded -> go to students list page
if success {
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.performSegueWithIdentifier("studentsList", sender: self)
})
} else {
// Authentification failed
print(evaluationError?.description)
//print out the specific error
switch evaluationError!.code {
case LAError.SystemCancel.rawValue:
print("Authentication cancelled by the system")
case LAError.UserCancel.rawValue:
print("Authentication cancelled by the user")
default:
print("Authentication failed")
}
}
})
}
}
shouldPerformSegueWithIdentifier:
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
if (false) { //TODO -> username.text!.isEmpty || password.text!.isEmpty
notify("Login failed", message: "Please enter your username and password to proceed")
return false
} else if (false) { //TODO when backend ready! -> !login("bucketFit", password: "test")
notify("Incorrect username or password", message: "Please try again")
return false
//if the login page is loaded after background, dont proceed (then we need to present the last presented view on the stack before the app leaved to background)
} else if let alreadyShown : AnyObject? = def.objectForKey("alreadyShown") {
if (alreadyShown != nil){
//TODO check whether login data is correct
dismissLoginView()
return false
}
}
return true
}
Thank you in advance.
What you could do is create a AuthenticationManager. This manager would be a shared instance which keep track of whether authentication needs to be renewed. You may also want this to contain all of the auth methods.
class AuthenticationManager {
static let sharedInstance = AuthenticationManager()
var needsAuthentication = false
}
In AppDelegate:
func willEnterForeground() {
def.setObject(true, forKey: "alreadyShown")
if let backgroundEntered : AnyObject? = def.objectForKey("backgroundEntered") {
let startTime = backgroundEntered as! NSDate
//number of seconds the app was in the background
let inactivityDuration = NSDate().timeIntervalSinceDate(startTime)
//if the app was longer than 3 minutes inactiv, ask the guide to input his password
if (inactivityDuration > 2) {
AuthenticationManager.sharedInstance.needsAuthentication = true
}
}
}
Then, subclass UIViewController with a view controller named SecureViewController. Override viewDidLoad() in this subclass
override fun viewDidLoad() {
super.viewDidLoad()
if (AuthenticationManager.sharedInstance().needsAuthentication) {
// call authentication methods
}
}
Now, make all your View Controllers that require authentication subclasses of SecureViewController.

Resources