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 t
This worked for ios 12 and 10:
if (@available(iOS 10, *)) {
passwordTextField.textContentType = UITextContentTypeStreetAddressLine2;
}
if (@available(iOS 12, *)) {
passwordTextField.textContentType = UITextContentTypeOneTimeCode;
}
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:
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!
for SwiftUI do as follow:
SecureField("Password", text: "some text").disableAutocorrection(true)
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.
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.
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.