How to detect when user used Password AutoFill on a UITextField How to detect when user used Password AutoFill on a UITextField ios ios

How to detect when user used Password AutoFill on a UITextField


Not sure if the previous answer stopped working at some point, but I can't get it to work—I only get a single didBeginEditing call when AutoFill is used.

However, I did find a way to detect AutoFill. And keep in mind that it is possible for AutoFill to be used after some characters have already been entered, for example if the user has already typed some numbers in the phone number, then they AutoFill the full number.

For Swift 4/5:

private var fieldPossibleAutofillReplacementAt: Date?private var fieldPossibleAutofillReplacementRange: NSRange?func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {    // To detect AutoFill, look for two quick replacements. The first replaces a range with a single space    // (or blank string starting with iOS 13.4).    // The next replaces the same range with the autofilled content.    if string == " " || string == "" {        self.fieldPossibleAutofillReplacementRange = range        self.fieldPossibleAutofillReplacementAt = Date()    } else {        if fieldPossibleAutofillReplacementRange == range, let replacedAt = self.fieldPossibleAutofillReplacementAt, Date().timeIntervalSince(replacedAt) < 0.1 {            DispatchQueue.main.async {                // Whatever you use to move forward.                self.moveForward()            }        }        self.fieldPossibleAutofillReplacementRange = nil        self.fieldPossibleAutofillReplacementAt = nil    }    return true}


Found a solution.

When the password manager is used to autofill username + password, it will trigger didBeginEditing twice, faster than a human ever could.

So, I calculate the time between the events. If the time is extremely fast, then I assume that autofill (e.g. FaceID or TouchID) was used to enter credentials and auto-trigger whatever UI is next -- in my case, the User tapping "Sign-in".

Obviously, you have to set up the correct delegation of the UITextFields you want to monitor, but once you do that:

var biometricAutofillTime: Date!func textFieldDidBeginEditing(_ textField: UITextField) {    if biometricAutofillTime != nil {        if Date().timeIntervalSince(biometricAutofillTime) < 0.1 {            // NOTE: Need to hesitate for a very short amount of time,            //        because, otherwise, the second UITextField (password)            //        won't yet be populated            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { self.didTapSignin() }        }        biometricAutofillTime = nil    }    biometricAutofillTime = Date()}


This detects when user has autofilled via passwords. It may also trigger when user pastes text from their clipboard. (If textfield is empty)

You can probably handle the logic to remove user pasted cases with this link..how to know when text is pasted into UITextView

  private var didAutofillTextfield: Bool = false {    didSet {      if didAutofillTextfield {        // Fire analytics for user autofilling      }    }  } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {    // If the range is {0,0} and the string count > 1, then user copy paste text or used password autofill.    didAutofillTextfield = range == NSRange(location: 0, length: 0) && string.count > 1    return true  }