Disable "Save Password" action sheet when exiting UIViewController?
Asked Answered
I

3

6

My app has a "Create Account" view controller (shown below) that prompts the user to enter a username and password. Whenever I segue to another view controller, I get a pop-up action sheet prompting to save the password in the keychain.

This is a nifty little freebie IF the user successfully creates the new account. But I get this same pop-up if the user hits the cancel (back) button in the navigation bar, if they select the option to use Facebook login instead of creating an account, or any other means for leaving this view controller (see figures below).

How can I get this popup to ONLY show up when the user successfully creates a new account?

EDIT: Per request, here is the code that is related to the segues that result in the appearance of the "Save Password" action sheet.

from CreateAccountViewController.swift:

class CreateAccountViewController : UIViewController
{
  // ... bunch of irrelevant code deleted ...

  // bound to "Connect with Facebook" button (see image below)
  @IBAction func switchToFacebook(_ sender : UIButton)
  {
    performSegue(.SwitchToFacebookLogin, sender: sender)
  }
  // ... bunch of irrelevant code deleted ...
}

extension CreateAccountViewController : GameServerAlertObserver
{
  // callback based on response from GameCenter after 
  //  submitting a "create new user" request
  func handleConnectionResponse(_ response:GameServerResponse )
  {
    switch response
    {
    // ... other response cases removed ...
    case .UserCreated:
      self.removeSpinner()
      performSegue(.CreateAccountToStartup, sender: self)

    default:
      response.displayAlert(over: self, observer: self)
      self.removeSpinner()
    }
  }

  // Functions defined in the GameServerAlertObserver protocol
  //   to handle user response to "User Exists Popup" (figure below)    
  func ok()
  {
    // user chose to enter new  password... clear the existing username field
    usernameTextField.text = ""
  }

  func cancel()
  {
    // segue back to the startup view controller
    performSegue(.CreateAccountToStartup, sender: self)
  }

  func goToLogin()
  {
    // segue to the login view controller
    performSegue(.SwitchToAccountLogin, sender:self)
  }
}

from UIViewController_Segues:

enum SegueIdentifier : String
{
  case LoserBoard             = "loserBoard"
  case CreateAccount          = "createAccount"
  case AccountLogin           = "accountLogin"
  case FacebookLogin          = "facebookLogin"
  case SwitchToFacebookLogin  = "switchToFacebookLogin"
  case SwitchToAccountLogin   = "switchToAccountLogin"
  case CreateAccountToStartup = "createAccountToStartup"
  case AccountLoginToStartup  = "accountLoginToStartup"
  case FacebookLoginToStartup = "facebookLoginToStartup"
  case UnwindToStartup        = "unwindToStartup"
}

extension UIViewController
{ 
  func performSegue(_ target:SegueIdentifier, sender:Any?)
  {
    performSegue(withIdentifier: target.rawValue, sender: sender)
  }
}

from GameServerAlert.swift:

protocol GameServerAlertObserver
{
  func ok()
  func cancel()
  func goToLogin()
}

extension GameServerResponse
{
  func displayAlert(over controller:UIViewController, observer:GameServerAlertObserver? = nil)
  {
    var title   : String
    var message : String
    var actions : [UIAlertAction]

    switch self
    {
    // ... deleted cases/default which don't lead to segue ...

    case .UserAlreadyExists:
      title = "User already exists"
      message = "\nIf this is you, please use the login page to reconnect.\n\nIf this is not you, you will need to select a different username."
      actions = [
        UIAlertAction(title: "Go to Login page",   style: .default, handler: { _ in observer?.goToLogin() } ),
        UIAlertAction(title: "Enter new username", style: .default, handler: { _ in observer?.ok() } ),
        UIAlertAction(title: "Cancel",             style: .cancel,  handler: { _ in observer?.cancel() } )
      ]
    }

    let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
    actions.forEach { (action) in alert.addAction(action) }
    controller.present(alert,animated:true)
  }
}

Examples from the simulator:

Create Account - (user enters username and password for new account here.)

enter image description here

Facebook Login

If user decides to use Facebook to log in rather than creating a user account, they are taken to this view (which I still haven't fleshed out). Note that the "Save Password" action sheet has popped up.

enter image description here

User Exists Popup

If user attempts to create an account with a username that already exists, they will be presented with this popup. If they select Cancel, they are taken back to the startup screen (see below). If they select Enter new username, they are kept on the same screen with the username cleared out. If they select Login, they are taken to the login screen.

enter image description here

Startup Screen

If the user selects Cancel above, they are brought back here. Again, note that the "Save Password" action sheet has popped up.

enter image description here

Inapproachable answered 22/3, 2020 at 20:5 Comment(2)
have you been able to find a solution to this?Yippie
I ended up refactoring my design to get around the issue... I never actually solved it. But... I believe that mitch10e's response (below) may hold the key to the actual fix. I'm going to check it out later on an earlier version of my code.Inapproachable
T
2

Sorry about the short answer, I don't usually post on this site. This is the password Autofill that is happening on your device when the create user screen is dismissed.

Apple Documentation: https://developer.apple.com/documentation/security/password_autofill

Here is a link to a site that goes over all the requirements very well: https://developerinsider.co/ios12-password-autofill-automatic-strong-password-and-security-code-autofill/

Tympanites answered 8/5, 2020 at 14:13 Comment(2)
Thank you. I ended up making notable changes to my design in order to circumvent the problem. But, I will definitely take a look at the links you provided to see if that would have addressed my issue.Inapproachable
About 3/4 of the way down the second link, I found the criteria required for the automatic save popup to be shown. Looks like if I would have cleared the password fields prior to dismissing the login view, the popup would have failed the criteria and the auto save popup would not have been displayed. I'm going to upvote this answer for now. In a little bit, I'm going to see if I can recover the old version from git and test this out. If it does the trick, I'll mark this as the answer. Thank you.Inapproachable
A
4

What I do to avoid the automatic Password saving action sheet when the user :

  • dismiss the login view controller ;
  • pop the view controller ;
  • use interactive pop gesture.

=>

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
      passwordTextField.textContentType = .password
    }
  }

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    if isMovingFromParent || isBeingDismissed || parent?.isBeingDismissed == true {
      passwordTextField.textContentType = nil
    }
  }
Aundrea answered 30/5, 2020 at 15:43 Comment(2)
I had to also clear the passwordTextField text to make this work. So add passwordTextField.text = nil to viewWillDisappear.Jedthus
Also make sure to do this only when you don't want the system to show the "Save Password" option. If the user actually did update their credentials, the content of viewWillDisappear should not be executed.Jedthus
T
2

Sorry about the short answer, I don't usually post on this site. This is the password Autofill that is happening on your device when the create user screen is dismissed.

Apple Documentation: https://developer.apple.com/documentation/security/password_autofill

Here is a link to a site that goes over all the requirements very well: https://developerinsider.co/ios12-password-autofill-automatic-strong-password-and-security-code-autofill/

Tympanites answered 8/5, 2020 at 14:13 Comment(2)
Thank you. I ended up making notable changes to my design in order to circumvent the problem. But, I will definitely take a look at the links you provided to see if that would have addressed my issue.Inapproachable
About 3/4 of the way down the second link, I found the criteria required for the automatic save popup to be shown. Looks like if I would have cleared the password fields prior to dismissing the login view, the popup would have failed the criteria and the auto save popup would not have been displayed. I'm going to upvote this answer for now. In a little bit, I'm going to see if I can recover the old version from git and test this out. If it does the trick, I'll mark this as the answer. Thank you.Inapproachable
G
-1

Add a condition before running the code block which shows the action sheet. You can do this simply with an if statement. This statement must check if the account has been successfully created or not. Code block which shows action sheet must run only when the condition is true.

Gwenni answered 23/3, 2020 at 4:54 Comment(3)
I am not explicitly showing the action sheet. It magically presents itself after a segue away from the "create account" view controller. It must be coming from somewhere in the UIKit... but I cannot find any documentation about it.Inapproachable
We can investigate it together if you can share the relevant code in your question. It is not easy to figure out the reason without seeing the code.Gwenni
Exactly what would you consider relevant code in this case? The very essence of my question is what triggers the Save Password" action sheet to be displayed when I segue to from the "Create Account" VC to any other VC. I have added the code that kicks off the segue, but I don't see how that will be helpful.Inapproachable

© 2022 - 2024 — McMap. All rights reserved.