94

As of now I would like to opt out of the new option iOS 11 gives, that is to suggest passwords in the app. When I run the app on iOS 11 I get the autofill option on top of the keyboard and my username and password textfield don't even show up.

So, my question is, how can I disable the new password autofill feature all together so the key on the keyboard is not shown at all and the overall behavior is the same as pre iOS 11?

enter image description here

zumzum
  • 17,984
  • 26
  • 111
  • 172
  • Try setting the username and password field's `textContentType` property to `.textContentType` - This should tell iOS 11 that your fields *aren't* username/password fields (even though they are) and prevent the accessory view being displayed; Something like ` self.passwordField.textContentType = .textContentType` – Paulw11 Aug 02 '17 at 05:51
  • @zumzum did you get any solution . please share – Nazmul Hasan Aug 10 '17 at 19:57
  • 2
    This is a problem for me as well. The autocomplete feature appears on the fields for signing up, which isn't desired. I'd like them just to be on the fields for logging in. Strange stuff. – Brad Root Sep 07 '17 at 02:11
  • 2
    Looks like on iOS12 it appears again. How did you solve it there? – dollar2048 Aug 01 '18 at 09:09
  • 1
    In iOS12, it still appears. Do you have any idea ? – Emrah Akgül Aug 08 '18 at 13:55
  • @EmrahAkgül check my answer below, a weird working workaround – Gal Shahar Sep 20 '18 at 14:25

23 Answers23

88

iOS 11 & 12 & 13 - Swift 4.2 & 5 (Updated):

if #available(iOS 12, *) {
    // iOS 12 & 13: Not the best solution, but it works.
    passwordTextField.textContentType = .oneTimeCode
} else {
    // iOS 11: Disables the autofill accessory view. 
    // For more information see the explanation below.
    emailTextField.textContentType = .init(rawValue: "")
    passwordTextField.textContentType = .init(rawValue: "")
}

iOS 11 explanation:

Make sure you setup all of your UITextField objects like this.

If you have for example an UITextField object where the user must enter his email address and another one where the user must enter his password assign UITextContentType("") to both of their textContentType property. Otherwise it will not work and the autoFill accessory view will still be shown.

shim
  • 9,289
  • 12
  • 69
  • 108
Baran
  • 2,710
  • 1
  • 23
  • 23
  • 1
    It's available form iOS 10, not iOS 11. – matm Mar 12 '18 at 11:30
  • @GalShahar I can't test it right now but here is my suggestion: iOS 12 introduces a new `UITextContentType` which is called `newPassword ` (see: https://developer.apple.com/documentation/uikit/uitextcontenttype/2980929-newpassword). Try setting the password text fields content type to this type. I guess iOS will not show the autofill accessory view then, because the user is forced to setup a new password and not use/access one that was setup before by using the autofill accessory view. Right now this is only theory. I'm not sure whether this will work, but let me know whether it does! – Baran Sep 21 '18 at 11:50
  • Okay guys forget about what I wrote about iOS 12. Setting `UITextContentType ` to `newPassword` does not work. I tried the solution of @GalShahar, but I didn't like it. Instead I'm setting the `UITextContentType` to `oneTimeCode `. That works for now. – Baran Oct 01 '18 at 09:01
  • For iOS 12, I had to set ```isSecureTextEntry``` to false first in addition to set ```UITextContentType``` to ```oneTimeCode```. We can set ```isSecureTextEntry``` to whatever we want once they start typing the text field. – da1 Jan 22 '19 at 19:16
  • 1
    @da1 We are setting `.isSecureTextEntry` to `true` before setting `textContentType` to `.oneTimeCode` and it works as expected. I don't know how your code looks like, but when initializing the text field the order of setting up it's properties is not important. – Baran Jan 23 '19 at 13:31
  • it doesn't work when change input focus from user name to password – Kumaresan P Feb 28 '19 at 13:57
  • @KumaresanP try setting `textContentType` on both of your text fields (user name + password) – Baran Feb 28 '19 at 14:13
  • @Bem yes did both works partially, problem is when switch from normal text type to secure text and do wise versa – Kumaresan P Feb 28 '19 at 15:33
  • @KumaresanP why do you switch the `textContentType`? Marking your text field with `isSecureTextEntry` should also work. Or do you use one text field for both entries (email address + password -> like when the user did enter his email address the same text field is used to enter the password)? – Baran Mar 01 '19 at 11:26
  • @Bem actually doing toggle between secure text entry as false and true to recreate it. – Kumaresan P Mar 05 '19 at 10:23
  • @KumaresanP I think this could be the issue. Instead of switching `isSecureTextEntry` too true and false create two text fields. One for your the user's email address input and one for the user's password input. Make sure to setup both correctly with the suggested `textContentType` above. Add and position the password field on top of the email address input field. Set the `isHidden` property of the password text field to `true` and when the user is finished with the email address you can set `isHidden` of the password text field to `false` and of the email address text field input to `true`. – Baran Mar 05 '19 at 12:31
  • `passwordTextField.textContentType = .oneTimeCode` not works with iphone 6s ios 13.5 – Sandeep Maurya Jul 02 '20 at 14:17
  • @SandeepMaurya Did you found a solution? – Baran Jul 28 '20 at 10:10
  • @BaranEmre no, I'm not what I'm doing is initialy leave textfield as normal. and once user start typing I change textfield to isSecureText = true. tried all solutions not a single work – Sandeep Maurya Jul 28 '20 at 10:21
18

iOS 12 seems to recognise password textFields also by isSecureTextEntry property and not just by textContentType property, so making this accessory view disappear is not really possible unless you both set textContentType to nothing, and remove the secureEntry feature (and cause a security flaw in your app) which then prevents iOS 12 to recognise the textField as a password textField and show this annoying accessory view.

In my case the accessory caused a bug which made my app unresponsive when tapped (Which also got my app rejected in app review process). So I had to remove this feature. I didn't want to give on up this security feature so I had to solve things by my self.

The idea is to remove the secureEntry feature but add it by yourself manually. It did worked:

enter image description here


It can be done like that:

Swift 4 way:

First, as answered here, set textContentType to nothing:

if #available(iOS 10.0, *) {
    passwordText.textContentType = UITextContentType("")
    emailText.textContentType = UITextContentType("")
}

Than, declare a String variable which will later contain our textField real content:

var passwordValue = ""

Add a target to the passwordTextField, which will be called each time the textField content changes:

passwordText.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)

Now That's what will do the magic, declare the function that will handle the text replacements:

@objc func textFieldDidChange(_ textField: UITextField) {
    if textField.text!.count > 1 {
        // User did copy & paste
        if passwordValue.count == 0 { // Pasted into an empty textField
            passwordValue = String(textField.text!)
        } else { // Pasted to a non empty textField
            passwordValue += textField.text!.substring(from: passwordValue.count)
        }
    } else {
        // User did input by keypad
        if textField.text!.count > passwordValue.count { // Added chars
            passwordValue += String(textField.text!.last!)
        } else if textField.text!.count < passwordValue.count { // Removed chars
            passwordValue = String(passwordValue.dropLast())
        }
    }
    self.passwordText.text = String(repeating: "•", count: self.passwordText.text!.count)
}

Finally, Set textField's autocorrectionType to .no to remove predictive text:

passwordText.autocorrectionType = .no

That's it, use passwordValue to perform your login.

Hope it'll help someone.

UPDATE

It catches pasted values also, forgot to add it before.

Gal Shahar
  • 2,695
  • 1
  • 21
  • 29
  • 2
    Super! Nice hack buddy! shame that iOS makes us hack rather than providing cleaner ways to do the most basic things. This should be the accepted answer. – sandpat Sep 24 '18 at 12:50
  • Downvoted because the logic makes no sense. Why would `if textField.text!.count > 1` mean that a user copy pasted? And if a user deleted characters, `passwordValue.dropLast()` assumes a user always deletes from the end. What if a user deletes a range of characters in the middle somewhere? – youjin Dec 02 '21 at 17:35
10

The feature can be disabled by specifying a content type that is neither username nor password. For example, if the user should enter an email address, you could use

usernameTextField?.textContentType = .emailAddress
gebirgsbärbel
  • 2,327
  • 1
  • 22
  • 38
  • 4
    Interestingly I have an email address field above a password field, and the email address field offers an auto-complete. – Brad Root Sep 07 '17 at 02:10
  • 1
    @BradRoot change your password field textContentype too! if your email is already saved in keychain then it will show the info in quickbar, so better to user .nickname or try this code if #available(iOS 10.0, *) { self.passwordTextField.textContentType = UITextContentType.init(rawValue: "") } else { // Fallback on earlier versions } – Sahil Sep 28 '17 at 05:48
9

in response to @Gal Shahar Answer.

iOS 12 recognise password textFields by isSecureTextEntry property and not just by textContentType property.

Way Around to bypass Auto-fill Suggestion.

  1. set isSecureTextEntry property to false.

self.passwordTextField.secureTextEntry = NO;

  1. Add a UITextField Delegate Method and enable the isSecureTextEntry property.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField == self.passwordTextField && !self.passwordTextField.secureTextEntry) {
        self.passwordTextField.secureTextEntry = YES;
    }

    return YES;
}

NOTE: - Do NOT Use shouldBeginEditing UITextField delegate method it Will Still show Auto-filling Suggestion. Do NOT Use textFieldDidChange UITextField delegate method it Will Auto-delete the first charachter as the it Will happen after the first charachter is displayed. And 'secureTextEntry' will empty the field.

ashish
  • 351
  • 3
  • 7
  • 1
    This not only solves a discussed problem but also solves the problem of misreading a keyboard height from the UIKeyboardWillShowNotification when initially tapping on the password field. Great answer. – ekashking Apr 17 '20 at 13:29
8

You can add extension for UITextContentType like this

extension UITextContentType {
    public static let unspecified = UITextContentType("unspecified")
}

after that, you can use it

if #available(iOS 10.0, *) {
    passwordField.textContentType = .unspecified
}
Mikhail Zinov
  • 324
  • 2
  • 12
6

A very simple approach in ios11 worked for me. Suppose your iboutlets are usernametextfield and passwordtextfield. In viewDidLoad() function of your viewcontroller that holds the both outlest use the following code

usernametextfield.textContentType = UITextContentType("")
passwordtextfield.textContentType = UITextContentType("")

After this you wont see autofill accessory option when you tap on your textfields.

Ammad
  • 341
  • 6
  • 7
6

Objective-C

if (@available(iOS 10, *)){
    self.tfEmail.textContentType = @"";
    self.tfPassword.textContentType = @"";
}

This worked for me.

4

In my case the solution with setting textContentType = .oneTimeCode for password fields worked only partially. On the device with iOS 15 I did not saw a problem but on the simulator with iOS 15 it did not work properly especially when switching between the fields. Also it's worth saying that I had a button for showing/hiding passwords in fields which toggle the value in isSecureTextEntry. However after setting textContentType = .oneTimeCode on all fields on the screen (not only password fields but also other name and email fields which I had) then it started to work properly also on the simulator. So if the .oneTimeCode solution does not work for you then you might want to try setting it on all fields on your screen not only password fields.

Leszek Szary
  • 9,763
  • 4
  • 55
  • 62
3

Autofill is by default enabled for users. iOS saves all passwords in the keychain and make them available in keyboard in your apps. UITextView and UITextField automatically considered for AutoFill password. you can disable by specifying a content type that is neither username nor password but if the content type info already stored in keychain it will show in the quick bar. so better to assign empty UITextContentType type and it will not show quickbar.

Example:

  if #available(iOS 10.0, *) {
  self.textField.textContentType = UITextContentType("")
  } else {
  // Fallback on earlier versions
 }
Sahil
  • 9,096
  • 3
  • 25
  • 29
3

Objective C, iOS 15:

textField.textContentType = UITextContentTypeOneTimeCode;
textField.autocorrectionType = UITextAutocorrectionTypeNo;

On the simulator, it still may show suggestions, on the device doesn't.

Denis Kutlubaev
  • 15,320
  • 6
  • 84
  • 70
3

This worked for ios 12 and 10:

if (@available(iOS 10, *)) {
    passwordTextField.textContentType = UITextContentTypeStreetAddressLine2;
}

if (@available(iOS 12, *)) {
    passwordTextField.textContentType = UITextContentTypeOneTimeCode;
}
no_fate
  • 1,625
  • 14
  • 22
3

Crazy staff happening in this topic. I've made without iOS proposing me a password, but given me an autofill for email only. Just if someone need it so. After different combinations and different type of textContentType I've made it as I wanted.

  1. Email Text field with iOS autofill proposing be something.
  2. Password text field with no iOS system proposing me a new password, but filling it with password if I choose it from email text field.
  3. Password text field to have secure entry text.

And with this code it worked. Doesn't matter if you have email or username it will make you a proposition with what you need. So I've disabled accessory autofill view and left only autofill in toolbar of keyboard.

self.passwordField.isSecureTextEntry = true

if #available(iOS 11.0, *) {
    self.emailField.textContentType = .username
    self.emailField.keyboardType = .emailAddress
}

if #available(iOS 12.0, *) {
    self.passwordField.textContentType = .password
    self.passwordField.keyboardType = .default
}
Ivan Tkachenko
  • 489
  • 3
  • 10
2

You could try different answers here that conclude it's likely possible to remove the accessory view. But this leaves some bugs.

You could try to implement a custom keyboard perhaps, only for password fields. Also try to disable suggestions for your textfield, I think that also hides the accessoryView.

EDIT: Still no answer on Apple forums on the same question. Also I couldn't find anything regarding this in official UITextField documentation.

shim
  • 9,289
  • 12
  • 69
  • 108
Rishabh
  • 465
  • 5
  • 14
2

You can "turn off" the username/password combo detection by assigning a dummy textContentType to the password text field.

passwordFormField.textContentType = UITextContentType("dummy")

This turned off the key symbol for both the password field and the email field that preceded it, and in this way you don't use one of the predefined values and you avoid showing unrelated suggestions in the keyboard accessory view.

  • Does this still work on the latest iOS 12 beta for you? – pfandrade Aug 09 '18 at 11:22
  • No it does not. On iOS 12 it detects this field as a new password field and suggests a new strong password (new iOS 12 feature). I actually want this behavior in my case, so I'm tagging this password field with the new iOS 12 `newPassword` UITextContentType . I don't know how to avoid this new behavior though. – Miguel Cabeça Aug 20 '18 at 07:28
  • For iOS 12 beta, if use: textContentType = UITextContentType.oneTimeCode. Then, it doesn't have the keychain on the keyboard. It seems to work fine for me without any side effects. If you use .newPassword, that also works, but then it asks you to save the password once you finish with the password. – Daniel Jones Sep 05 '18 at 21:22
2

Ok, I can confirm that I have the following working on iOS 14 with no issues:

// once this property is declared, textField.keyboardType does
// not seem to have any effect in showing the autofill

textField.textContentType = UITextContentType.oneTimeCode
textField.keyboardType = UIKeyboardType.emailAddress

UITextField.textContentType

Paul D.
  • 156
  • 2
  • 12
1

From what I can tell, Bem's answer does not work in iOS 12 and Gal Shahar's answer does not account for some edge cases (for example, if a user deletes multiple characters at once). I worked around this using an IBAction, thus removing the necessity to check for iOS version altogether. I'm just a beginner, so this might not be the "best" answer or the most efficient, but it made the most sense to me:

First, uncheck "Secure Text Entry" in the Storyboard or set it to "false"/"NO" via code for your password UITextField. This will prevent iOS from attempting to AutoFill.

Then, link your password UITextField to an IBAction. Mine is called on:

  • Editing did begin
  • Editing did change
  • Editing did end

The IBAction function I wrote determines the differences between a user's starting password and what has been inputed into the password UITextField and creates a new password based on this information:

class Login: UIViewController {
    var password = ""

    override func viewDidLoad() { super.viewDidLoad() }

    @IBAction func editPasswordField(_ sender: UITextField) {
        var input = Array(sender.text ?? "")
        var oldPassword = Array(password)
        var newPassword = Array("")

        //if character(s) are simply deleted from "passwordField" (not replaced or added to), "cursorPosition" is used to determine which corresponding character(s) need to also be removed from "oldPassword"
        //this is indicated by "input" comprising of only "•" (bullets) and being shorter in length than "oldPassword"
        var onlyBullets = true
        for char in input { if char != "•" { onlyBullets = false } }
        if onlyBullets && input.count < oldPassword.count {
            if let selectedRange = sender.selectedTextRange {
                let cursorPosition = sender.offset(from: sender.beginningOfDocument, to: selectedRange.start)
                let prefix = String(oldPassword.prefix(cursorPosition))
                let suffix = String(oldPassword.suffix(input.count - cursorPosition))
                input = Array(prefix + suffix)
            } else { input = Array("") }
        }

        //if no changes were made via input, input would comprise solely of a number of bullets equal to the length of "oldPassword"
        //therefore, the number of changes made to "oldPassword" via "input" can be measured with "bulletDifference" by calculating the number of characters in "input" that are NOT bullets
        var bulletDifference = oldPassword.count
        for char in input { if char == "•" { bulletDifference -= 1 } }

        //the only way "bulletDifference" can be less than 0 is if a user copy-pasted a bullet into "input", which cannot be allowed because it breaks this function
        //if a user pastes bullet(s) into "input", "input" is deleted
        //an edge case not accounted for is pasting a mix of characters and bullets (i.e. "ex•mple") when "oldPassword.count" exceeds the number of bullets in the mixed input, but this does not cause crashes and therefore is not worth preventing
        if bulletDifference < 0 {
            bulletDifference = oldPassword.count
            input = Array("")
        }

        //"bulletDifference" is used to remove every character from "oldPassword" that corresponds with a character in "input" that has been changed
        //a changed character in "input" is indicated by the fact that it is not a bullet
        //once "bulletDifference" equals the number of bullets deleted, this loop ends
        var bulletsDeleted = 0
        for i in 0..<input.count {
            if bulletsDeleted == bulletDifference { break }
            if input[i] != "•" {
                oldPassword.remove(at: i - bulletsDeleted)
                bulletsDeleted += 1
            }
        }

        //what remains of "oldPassword" is used to substitute bullets in "input" for appropriate characters to create "newPassword"
        //for example, if "oldPassword" is "AcbDE" and "input" is "•bc••", then "oldPassword" will get truncated to "ADE" and "newPassword" will equal "A" + "bc" + "DE", or "AbcDE"
        var i = 0
        for char in input {
            if char == "•" {
                newPassword.append(oldPassword[i])
                i += 1
            } else { newPassword.append(char) }
        }
        password = String(newPassword)

        //"passwordField.text" is then converted into a string of bullets equal to the length of the new password to ensure password security in the UI
        sender.text = String(repeating: "•", count: password.count)
    }
}

Constructive criticism is appreciated!

Escargot
  • 11
  • 3
1

enter image description here

I have attached the screenshot. you can change the content Type as Username in the storyboard or you can do programatically. you may create an extension for UITextfield .

func diableAutofill() {
        self.autocorrectionType = .no
        if #available(iOS 11.0, *) {
            self.textContentType = .username
        } else {
            self.textContentType = .init("")
        }
    }
siddhant
  • 39
  • 2
1

change textfield content type to

Obj C

if (@available(iOS 12.0, *)) {
    self.curresntPasswordTxField.textContentType = UITextContentTypeOneTimeCode;
} else {
    // Fallback on earlier versions
}

Swift

self.curresntPasswordTxField.textContentType = .oneTimeCode
Fisky
  • 114
  • 5
0
self.passwordTextField.autocorrectionType = NO;

It does not seem to work, the keychain sign still there,

self.passwordTextField.textContentType = UITextContentTypeName;

The code above does work, but if the users set up their Apple ID account, Then, the name of the apple id will be display on the keyboard you cannot disable it by set autocorrectionType to No, not sure if Apple still refines this autofill feature, it's quite buggy right now.

Ankit Jayaswal
  • 5,549
  • 3
  • 16
  • 36
Roger Han
  • 39
  • 3
  • 1
    This type of 'answer' should be reserved for the comments section, as it doesn't give an actual answer or link to any reference documentation from apple etc. Welcome to SO though! – stktrc Aug 04 '17 at 04:00
  • no solution yet. Nothing listed here worked well for me. – zumzum Aug 15 '17 at 16:46
0

This worked for me:

NOTE: try putting this code on the password, password confirm (if applicable), AND email textfields. I was not putting it on the email textfield and it was still popping up for the two password fields.

if #available(iOS 12, *) {
     // iOS 12: Not the best solution, but it works.
     cell.textField.textContentType = .oneTimeCode
} else {
     // iOS 11: Disables the autofill accessory view.
     cell.textField.textContentType = .init(rawValue: "")
}
Paul Lehn
  • 3,202
  • 1
  • 24
  • 29
0

I think set all UITextField textContentType in form to UITextContentType("") or .oneTimeCode is not a clean solution. Enable/Disable isSecureTextEntry still give you the same issue.

@Gal Shahar 's Answer is nice but it is still not perfect. The masked char is not the same as the masked char that used in secure entry text from apple. It should use Unicode Character 'BLACK CIRCLE' (U+25CF) https://www.fileformat.info/info/unicode/char/25cf/index.htm

Also, it is not handling cursor movement. It will change the cursor position to the end of the text when inserting text in the middle. It will give you the wrong value when selecting and replacing text.

When you decide to use custom isSecureEntryText to avoid autofill password, here is the code:

Swift 5 (simple version)

@IBOutlet weak var passwordTextField: UITextField!

var maskedPasswordChar: String = "●"
var passwordText: String = ""
var isSecureTextEntry: Bool = true {
    didSet {
        let selectedTextRange = passwordTextField.selectedTextRange
        passwordTextField.text = isSecureTextEntry ? String(repeating: maskedPasswordChar, count: passwordText.count) : passwordText
        passwordTextField.selectedTextRange = selectedTextRange
    }
}

//this is UITextFieldDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if textField == passwordTextField {
        //update password string
        if let swiftRange = Range(range, in: passwordText) {
            passwordText = passwordText.replacingCharacters(in: swiftRange, with: string)
        } else {
            passwordText = string
        }

        //replace textField text with masked password char
        textField.text =  isSecureTextEntry ? String(repeating: maskedPasswordChar, count: passwordText.count) : passwordText

        //handle cursor movement
        if let newPosition = textField.position(from: textField.beginningOfDocument, offset: range.location + string.utf16.count) {
            textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
        }
        return false
    }
    return true
}

Swift 5 (COMPLETE version with securing last char animation)

private struct Constants {
    static let SecuringLastCharPasswordDelay = 1.5
}

@IBOutlet weak var passwordTextField: UITextField!

private var secureTextAnimationQueue: [String] = []

var maskedPasswordChar: String = "●"
var passwordText: String = ""
var isSecureTextEntry: Bool = true {
    didSet {
        secureTextAnimationQueue.removeAll()
        let selectedTextRange = passwordTextField.selectedTextRange
        passwordTextField.text = isSecureTextEntry ? String(repeating: maskedPasswordChar, count: passwordText.count) : passwordText
        passwordTextField.selectedTextRange = selectedTextRange
    }
}

//this is UITextFieldDelegate
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if textField == passwordTextField {
        //update password string
        if let swiftRange = Range(range, in: passwordText) {
            passwordText = passwordText.replacingCharacters(in: swiftRange, with: string)
        } else {
            passwordText = string
        }

        //replace textField text with masked password char
        updateTextFieldString(textField, shouldChangeCharactersIn: range, replacementString: string)

        //handle cursor movement
        if let newPosition = textField.position(from: textField.beginningOfDocument, offset: range.location + string.utf16.count) {
            textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
        }
        return false
    }
    return true
}

private func updateTextFieldString(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) {
    if isSecureTextEntry {
        if string.count == .one, let text = textField.text {
            let maskedText = String(repeating: maskedPasswordChar, count: text.count)

            var newMaskedText = String()
            if let swiftRange = Range(range, in: maskedText) {
                newMaskedText = maskedText.replacingCharacters(in: swiftRange, with: string)
            } else {
                newMaskedText = text + maskedText
            }

            textField.text = newMaskedText
            secureTextAnimationQueue.append(string)
            asyncWorker.asyncAfter(deadline: .now() + Constants.SecuringLastCharPasswordDelay) { [weak self] in
                self?.securingLastPasswordChar()
            }
        } else {
            secureTextAnimationQueue.removeAll()
            textField.text = String(repeating: maskedPasswordChar, count: passwordText.count)
        }
    } else {
        textField.text = passwordText
    }
}

private func securingLastPasswordChar() {
    guard secureTextAnimationQueue.count > .zero, isSecureTextEntry else { return }
    secureTextAnimationQueue.removeFirst()
    if secureTextAnimationQueue.count == .zero {
        let selectedTextRange = passwordTextField.selectedTextRange
        passwordTextField.text = String(repeating: maskedPasswordChar, count: passwordText.count)
        passwordTextField.selectedTextRange = selectedTextRange
    }
}
Sandy Akbar
  • 441
  • 4
  • 6
0

Thanks to Apple, I couldn't find any way with native methods when isSecureTextEntry setted to YES. Gal Shahar's way is the only solution for disabling password autofill accessory view option. But It's more easy to do with

objective c

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

swift

textField(_:shouldChangeCharactersIn:replacementString:)

delegate. And use simple code like this. Declare a String variable which will later contain our textField real content, mine is pswd.

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
    {
        //Thanks iOS13!!!
        if(!_pswd)
        {
            _pswd = @"";
        }
        _pswd = [_pswd stringByReplacingCharactersInRange:range withString:string];

        if (!buttonShowPassword.selected)
        {
            textField.text = [@"" stringByPaddingToLength:_pswd.length withString: @"•" startingAtIndex:0];
        }
        else
        {
            textField.text = _pswd;
        }
        return NO;
    }
0

for SwiftUI do as follow:

 SecureField("Password", text: "some text").disableAutocorrection(true)
Payam Khaninejad
  • 7,692
  • 6
  • 45
  • 55