A partir de ahora, me gustaría excluirme de la nueva opción que ofrece iOS 11, es decir, sugerir contraseñas en la aplicación. Cuando ejecuto la aplicación en iOS 11, aparece la opción de autocompletar en la parte superior del teclado y el campo de texto de mi nombre de usuario y contraseña ni siquiera aparecen.
Entonces, mi pregunta es, ¿cómo puedo deshabilitar la función de autocompletar nueva contraseña todos juntos para que la tecla en el teclado no se muestre en absoluto y el comportamiento general sea el mismo que antes de iOS 11?
textContentType
propiedad del campo de nombre de usuario y contraseña en.textContentType
: esto debería indicarle a iOS 11 que sus campos no son campos de nombre de usuario / contraseña (aunque lo sean) y evitar que se muestre la vista de accesorios; Algo como `self.passwordField.textContentType = .textContentType`Respuestas:
iOS 11 y 12 y 13 - Swift 4.2 y 5 (actualizado):
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: "") }
Explicación de iOS 11 :
Asegúrese de configurar todos sus
UITextField
objetos de esta manera.Si tiene por ejemplo un
UITextField
objeto donde el usuario debe ingresar su dirección de correo electrónico y otro donde el usuario debe ingresar su contraseña asignadaUITextContentType("")
a ambos de sutextContentType
propiedad. De lo contrario, no funcionará y se seguirá mostrando la vista de accesorios de Autocompletar.fuente
UITextContentType
que se llamanewPassword
(ver: developer.apple.com/documentation/uikit/uitextcontenttype/… ). Intente configurar el tipo de contenido de los campos de texto de la contraseña en este tipo. Supongo que iOS no mostrará la vista de accesorios de autocompletar en ese momento, porque el usuario se ve obligado a configurar una nueva contraseña y no usar / acceder a una que se configuró antes usando la vista de accesorios de autocompletar. Ahora mismo esto es solo teoría. No estoy seguro de si esto funcionará, ¡pero avíseme si funciona!UITextContentType
ennewPassword
no funciona. Probé la solución de @GalShahar, pero no me gustó. En su lugar, estoy configurando elUITextContentType
tooneTimeCode
. Eso funciona por ahora.isSecureTextEntry
primero tuve que configurarlo en falso además de configurarloUITextContentType
enoneTimeCode
. Podemos configurarisSecureTextEntry
lo que queramos una vez que comiencen a escribir el campo de texto..isSecureTextEntry
atrue
antes detextContentType
que.oneTimeCode
y funciona como se esperaba. No sé cómo se ve su código, pero al inicializar el campo de texto, el orden de configuración de sus propiedades no es importante.iOS 12 parece reconocer los campos de texto de contraseña también por
isSecureTextEntry
propiedad y no solo portextContentType
propiedad, por lo que hacer desaparecer esta vista de accesorios no es realmente posible a menos que ambos establezcan textContentType en nada y eliminen la función de entrada segura (y causen una falla de seguridad en su aplicación) que luego evita que iOS 12 reconozca el campo de texto como un campo de texto de contraseña y muestre esta molesta vista de accesorios.En mi caso, el accesorio causó un error que hizo que mi aplicación no respondiera cuando se tocaba (lo que también hizo que mi aplicación fuera rechazada en el proceso de revisión de la aplicación). Entonces tuve que eliminar esta función. No quería renunciar a esta función de seguridad, así que tuve que resolver las cosas por mi cuenta.
La idea es eliminar la función secureEntry pero agregarla usted mismo manualmente. Funcionó:
Se puede hacer así:
Rápido de 4 vías:
Primero, como se responde aquí, establezca
textContentType
nada:if #available(iOS 10.0, *) { passwordText.textContentType = UITextContentType("") emailText.textContentType = UITextContentType("") }
Entonces, declare una variable String que luego contendrá nuestro contenido real de textField:
var passwordValue = ""
Agregue un objetivo a passwordTextField, que se llamará cada vez que cambie el contenido de textField:
passwordText.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
Ahora eso es lo que hará la magia, declare la función que manejará los reemplazos de texto:
@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) }
Por último, Conjunto textField es
autocorrectionType
que.no
para eliminar el texto predictivo:Eso es todo, utilícelo
passwordValue
para realizar su inicio de sesión.Espero que ayude a alguien.
ACTUALIZAR
También captura valores pegados, se olvidó de agregarlos antes.
fuente
La función se puede desactivar especificando un tipo de contenido que no sea ni nombre de usuario ni contraseña. Por ejemplo, si el usuario debe ingresar una dirección de correo electrónico, puede usar
fuente
Puede agregar una extensión para UITextContentType de esta manera
extension UITextContentType { public static let unspecified = UITextContentType("unspecified") }
después de eso, puedes usarlo
if #available(iOS 10.0, *) { passwordField.textContentType = .unspecified }
fuente
Un enfoque muy simple en ios11 funcionó para mí. Suponga que sus iboutlets son usernametextfield y passwordtextfield. En la función viewDidLoad () de su controlador de vista que contiene los dos outlest use el siguiente código
usernametextfield.textContentType = UITextContentType("") passwordtextfield.textContentType = UITextContentType("")
Después de esto, no verá la opción de accesorio de autocompletar cuando toque en sus campos de texto.
fuente
en respuesta a @Gal Shahar Answer.
iOS 12 reconoce los campos de texto de contraseña por
isSecureTextEntry
propiedad y no solo portextContentType
propiedad.Camino para evitar la sugerencia de autocompletar.
isSecureTextEntry
propiedad en falso.self.passwordTextField.secureTextEntry = NO;
isSecureTextEntry
propiedad.- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (textField == self.passwordTextField && !self.passwordTextField.secureTextEntry) { self.passwordTextField.secureTextEntry = YES; } return YES; }
NOTA: - NO use el
shouldBeginEditing
método de delegado UITextField, seguirá mostrando la sugerencia de llenado automático. No NO UsotextFieldDidChange
método delegado UITextField se auto-eliminar la primera charachter como el que va a pasar después de que aparezca el primer y carentes. Y 'secureTextEntry' vaciará el campo.fuente
C objetivo
if (@available(iOS 10, *)){ self.tfEmail.textContentType = @""; self.tfPassword.textContentType = @""; }
Esto funcionó para mí.
fuente
Autocompletar está habilitado de forma predeterminada para los usuarios. iOS guarda todas las contraseñas en el llavero y las pone a disposición en el teclado de sus aplicaciones.
UITextView
yUITextField
se considera automáticamente para la contraseña de Autocompletar. puede desactivar especificando un tipo de contenido que no sea ni nombre de usuario ni contraseña, pero si la información del tipo de contenido ya está almacenada en el llavero, se mostrará en la barra rápida. así que es mejor asignar unUITextContentType
tipo vacío y no mostrará la barra rápida.Ejemplo:
if #available(iOS 10.0, *) { self.textField.textContentType = UITextContentType("") } else { // Fallback on earlier versions }
fuente
Esto funcionó para ios 12 y 10:
if (@available(iOS 10, *)) { passwordTextField.textContentType = UITextContentTypeStreetAddressLine2; } if (@available(iOS 12, *)) { passwordTextField.textContentType = UITextContentTypeOneTimeCode; }
fuente
Puede "desactivar" la detección combinada de nombre de usuario / contraseña asignando un muñeco
textContentType
al campo de texto de la contraseña.passwordFormField.textContentType = UITextContentType("dummy")
Esto desactivó el símbolo de la tecla tanto para el campo de contraseña como para el campo de correo electrónico que lo precedía, y de esta manera no usa uno de los valores predefinidos y evita mostrar sugerencias no relacionadas en la vista de accesorios del teclado.
fuente
newPassword
UITextContentType de iOS 12 . Sin embargo, no sé cómo evitar este nuevo comportamiento.Versión Objective C:
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) { self.passwordTextField.textContentType = @""; self.confirmPasswordTextField.textContentType = @""; }
dónde
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame) #define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending) #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
fuente
Por lo que puedo decir, la respuesta de Bem no funciona en iOS 12 y la respuesta de Gal Shahar no tiene en cuenta algunos casos extremos (por ejemplo, si un usuario elimina varios caracteres a la vez). Trabajé alrededor de esto usando una IBAction, eliminando así la necesidad de verificar la versión de iOS por completo. Soy solo un principiante, por lo que esta puede no ser la "mejor" respuesta o la más eficiente, pero tiene más sentido para mí:
Primero, desmarque "Entrada segura de texto" en el Storyboard o configúrelo en "falso" / "NO" mediante el código de su contraseña UITextField. Esto evitará que iOS intente Autocompletar.
Luego, vincule su contraseña UITextField a una IBAction. El mío está llamado:
La función IBAction que escribí determina las diferencias entre la contraseña inicial de un usuario y lo que se ha introducido en la contraseña UITextField y crea una nueva contraseña basada en esta información:
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) } }
¡Se agradece la crítica constructiva!
fuente
Puede probar diferentes respuestas aquí que concluyan que es posible eliminar la vista de accesorios. Pero esto deja algunos errores.
Quizás podría intentar implementar un teclado personalizado, solo para los campos de contraseña. También intente deshabilitar las sugerencias para su campo de texto, creo que también oculta el
accessoryView
.EDITAR: Todavía no hay respuesta en los foros de Apple sobre la misma pregunta. Además, no pude encontrar nada al respecto en la
UITextField
documentación oficial .fuente
Personal loco sucediendo en este tema. Lo hice sin que iOS me propusiera una contraseña, pero me dio un autocompletar solo para correo electrónico. Solo si alguien lo necesita. Después de diferentes combinaciones y diferentes tipos de
textContentType
cosas, lo hice como quería.Y con este código funcionó. No importa si lo tienes
email
ousername
te hará una propuesta con lo que necesitas. Así que desactivé la vista de autocompletar de accesorios y solo dejé el autocompletar en la barra de herramientas del teclado.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 }
fuente
self.passwordTextField.autocorrectionType = NO;
No parece funcionar, el letrero del llavero sigue ahí,
self.passwordTextField.textContentType = UITextContentTypeName;
El código anterior funciona, pero si los usuarios configuran su cuenta de ID de Apple, entonces, el nombre de la ID de Apple se mostrará en el teclado, no puede deshabilitarlo estableciendo autocorrectionType en No, no estoy seguro de si Apple aún refina esta función de autocompletar , tiene bastantes errores en este momento.
fuente
Esto funcionó para mí:
NOTA: intente poner este código en la contraseña, confirme la contraseña (si corresponde) Y los campos de texto del correo electrónico. No lo estaba poniendo en el campo de texto del correo electrónico y seguía apareciendo para los dos campos de contraseña.
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: "") }
fuente
Creo que establecer todo UITextField textContentType en forma
UITextContentType("")
o.oneTimeCode
no es una solución limpia. Habilitar / DeshabilitarisSecureTextEntry
todavía le da el mismo problema.La respuesta de @Gal Shahar es agradable, pero aún no es perfecta. El carácter enmascarado no es el mismo que el que se utilizó en el texto de entrada segura de Apple. Debe usar el carácter Unicode 'CÍRCULO NEGRO' (U + 25CF) https://www.fileformat.info/info/unicode/char/25cf/index.htm
Además, no controla el movimiento del cursor. Cambiará la posición del cursor al final del texto al insertar texto en el medio. Le dará un valor incorrecto al seleccionar y reemplazar texto.
Cuando decida utilizar isSecureEntryText personalizado para evitar la contraseña de autocompletar, aquí está el código:
Swift 5 (versión simple)
@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 (versión COMPLETA con animación de último carácter)
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 } }
fuente
Adjunto la captura de pantalla. puede cambiar el tipo de contenido como nombre de usuario en el guión gráfico o puede hacerlo mediante programación. puede crear una extensión para UITextfield.
func diableAutofill() { self.autocorrectionType = .no if #available(iOS 11.0, *) { self.textContentType = .username } else { self.textContentType = .init("") } }
fuente
Gracias a Apple, no pude encontrar ninguna forma con métodos nativos cuando isSecureTextEntry configurado en YES. El método de Gal Shahar es la única solución para deshabilitar la opción de vista de accesorios de autocompletar contraseña. Pero es más fácil de hacer con
C objetivo
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
rápido
textField(_:shouldChangeCharactersIn:replacementString:)
delegar. Y usa un código simple como este. Declare una variable String que luego contendrá nuestro contenido real de textField, el mío es 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; }
fuente