iOS autofill assumes the field before password is the username

Viewed 1186

The autofill works incredibly well, but I have one scenario when it isn't optimal and I am not aware of a work around a perhaps a proper way of doing it.

I have a screen with 2 UITextFields, first one is Amount, a monetary value to be transferred to another person. The second field is the password, the user will need to re-enter his password before the transaction can be completed.

The first field (Amount) has content type set as .unspecified and the second field (password) has it set to .password

When the user taps the second field Autofill beautifully suggest the the password to be used, but once the correct password is tapped, iOS automatically assumes the first field (amount) is the username and fills it with the username associated with the selected account, overwriting the amount the user had previously entered.

Is there a way to force password only autofill?

2 Answers

Today i face the same issue, with some different way. My situation is taking input of mobile number and password entry into the login page. Native app only support for mobile number while the web app support for email only. So while iOS autofill is in action, it fill the mobile number field with the email field, which is not acceptable.

After playing sometime with the autofill, i have found the life-cycle of the UITextField delegate is somewhat different in case of autofill.

When a autofill is tapped which is provided in the top of the keyboard, the UITextFieldDelegate start working from the beginning. Although the keyboard is open the delegate method started from the current with call order as follows

  1. textField(_:shouldChangeCharactersIn:replacementString:)
  2. textFieldShouldEndEditing(_:)

This delegate calls without the keyboard dismissing and re-appear again. This is unusual. Returning false in the textField(_:shouldChangeCharactersIn:replacementString:) has no effect in this case.

So theoretically i have the chance to edit the mobile field in the textFieldShouldEndEditing. To do that i keep track of the text which was present before the autofill begin. so took two variable as follows

var previousText: String?
var nextText: String?

Whenever a UITextField begin editing, i save it in previousText as following

public func textFieldDidBeginEditing(_ textField: UITextField) {
    previousText = textField.text
}

then i track the changes inside the textField(_:shouldChangeCharactersIn:replacementString:) as following

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    nextText = self.getCompleteString(original: textField.text, replacingRange: range, withString: string)


    // YOU MAY RETURN `true` OR `false` BASED ON KEYBOARD TYPING, BUT RETURNING `false` IN CASE OF AUTOFILL HAS NO EFFECT. SO I ASSUME, YOU RETURN `true` ALWAYS.
    return true;
}

func getCompleteString(original: String?, replacingRange: NSRange, withString: String) -> String? {
    guard var originalText = original else {
        return nil
    }

    guard let range = Range<String.Index>.init(replacingRange, in: originalText) else {
        return nil
    }

    originalText.replaceSubrange(range, with: withString)

    return originalText
}

Now the most interesting part, detecting custom requirement (in my case detecting a possible valid mobile number, where your case was detecting a valid amount)

func textFieldDidEndEditing(_ textField: UITextField) {
    if textField == MY_MOBILE_TEXT_FIELD {
       if nextText.IS_POSSIBLE_VALID_MOBILE_NUMBER() { // my function to detect the possible valid mobile number
           textField.text = nextText
       } else {
           textField.text = previousText
       }
    }
}

It worked for me, hope it works for you too.

Autofill disregards what textfield delegate methods return

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool 

So can try another hack which worked for me, You can set textContentType of amount text field to password type and use a toolbar on the keyboard to side autofill suggestions(Since you would be using num pad for entering digits in the amount field so you might already be using a custom toolbar).

amount_text_field.textContentType = .password

This way, iOS will assume it to be a password textfield and would not fill usernames or passwords which were applied from other textfields. And using toolbar should help you hide autofill suggestions on this textfield.

Related