iOS 11 Option zum automatischen Ausfüllen des Kennworts deaktivieren?

81

Ab sofort möchte ich die neue Option von iOS 11 deaktivieren, dh Passwörter in der App vorschlagen. Wenn ich die App unter iOS 11 ausführe, wird oben auf der Tastatur die Option zum automatischen Ausfüllen angezeigt, und mein Textfeld für Benutzername und Kennwort wird nicht einmal angezeigt.

Meine Frage ist also, wie ich die neue Funktion zum automatischen Ausfüllen von Passwörtern insgesamt deaktivieren kann, damit die Taste auf der Tastatur überhaupt nicht angezeigt wird und das allgemeine Verhalten dem vor iOS 11 entspricht.

Geben Sie hier die Bildbeschreibung ein

zumzum
quelle
Versuchen Sie, die textContentTypeEigenschaft des Felds für Benutzername und Kennwort auf .textContentType- festzulegen. Dies sollte iOS 11 mitteilen, dass Ihre Felder keine Felder für Benutzername / Kennwort sind (obwohl dies der Fall ist), und verhindern, dass die Zubehöransicht angezeigt wird. So etwas wie "self.passwordField.textContentType = .textContentType"
Paulw11
@zumzum hast du eine Lösung bekommen. Bitte teilen
Nazmul Hasan
2
Das ist auch für mich ein Problem. Die Funktion zur automatischen Vervollständigung wird in den Feldern für die Anmeldung angezeigt, was nicht erwünscht ist. Ich möchte, dass sie nur auf den Feldern sind, um sich einzuloggen. Seltsames Zeug.
Brad Root
2
Sieht aus wie auf iOS12 erscheint es wieder. Wie haben Sie es dort gelöst?
Dollar2048
In iOS12 wird es weiterhin angezeigt. Hast du irgendeine Idee ?
Emrah Akgül

Antworten:

78

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

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: "")
}

Erklärung zu iOS 11 :

Stellen Sie sicher, dass Sie alle Ihre UITextFieldObjekte so einrichten.

Wenn Sie beispielsweise ein UITextFieldObjekt haben, bei dem der Benutzer seine E-Mail-Adresse eingeben muss, und ein anderes Objekt, bei dem der Benutzer sein Kennwort eingeben muss, weisen Sie UITextContentType("")beide Objekte zu textContentType. Andernfalls funktioniert es nicht und die AutoFill-Zubehöransicht wird weiterhin angezeigt.

Baran Emre
quelle
1
Es ist für iOS 10 verfügbar, nicht für iOS 11.
12.
@GalShahar Ich kann es momentan nicht testen, aber hier ist mein Vorschlag: iOS 12 führt eine neue Version ein, UITextContentTypedie heißt newPassword (siehe: developer.apple.com/documentation/uikit/uitextcontenttype/… ). Versuchen Sie, den Inhaltstyp für Kennworttextfelder auf diesen Typ festzulegen. Ich denke, iOS zeigt dann die AutoFill-Zubehöransicht nicht an, da der Benutzer gezwungen ist, ein neues Kennwort einzurichten und kein zuvor eingerichtetes Kennwort mithilfe der AutoFill-Zubehöransicht zu verwenden / darauf zuzugreifen. Im Moment ist dies nur Theorie. Ich bin nicht sicher, ob dies funktionieren wird, aber lassen Sie mich wissen, ob es funktioniert!
Baran Emre
Okay, Leute vergessen, was ich über iOS 12 geschrieben habe. Die Einstellung UITextContentType auf newPasswordfunktioniert nicht. Ich habe die Lösung von @GalShahar ausprobiert, aber es hat mir nicht gefallen. Stattdessen setze ich das UITextContentTypeauf oneTimeCode . Das funktioniert jetzt.
Baran Emre
Für iOS 12, musste ich Satz isSecureTextEntryzu falschen zuerst zusätzlich zu Satz UITextContentTypezu oneTimeCode. Wir können einstellen isSecureTextEntry, was wir wollen, sobald sie das Textfeld eingeben.
da1
@ da1 Wir setzen .isSecureTextEntryauf , truebevor Sie textContentTypezu .oneTimeCodeund es funktioniert wie erwartet. Ich weiß nicht, wie Ihr Code aussieht, aber beim Initialisieren des Textfelds ist die Reihenfolge der Einrichtung seiner Eigenschaften nicht wichtig.
Baran Emre
13

iOS 12 scheint das Kennwort textFields auch nach isSecureTextEntryEigenschaften und nicht nur nach textContentTypeEigenschaften zu erkennen. Daher ist es nicht wirklich möglich, diese Zubehöransicht auszublenden, es sei denn, Sie setzen beide textContentType auf nichts und entfernen die SecureEntry-Funktion (und verursachen eine Sicherheitslücke in Ihrer App) verhindert dann, dass iOS 12 das textField als Kennwort textField erkennt und diese nervige Zubehöransicht anzeigt.

In meinem Fall verursachte das Zubehör einen Fehler, der dazu führte, dass meine App beim Tippen nicht mehr reagierte (wodurch meine App auch im App-Überprüfungsprozess abgelehnt wurde). Also musste ich diese Funktion entfernen. Ich wollte dieses Sicherheitsmerkmal nicht aufgeben, also musste ich die Dinge selbst lösen.

Die Idee ist, die SecureEntry-Funktion zu entfernen, sie jedoch manuell hinzuzufügen. Es hat funktioniert:

Geben Sie hier die Bildbeschreibung ein


Es kann so gemacht werden:

Schneller 4-Wege:

Zunächst, wie hier beantwortet, textContentTypeauf nichts gesetzt:

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

Deklarieren Sie dann eine String-Variable, die später unseren textField-Realinhalt enthält:

var passwordValue = ""

Fügen Sie dem passwordTextField ein Ziel hinzu, das jedes Mal aufgerufen wird, wenn sich der textField-Inhalt ändert:

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

Das ist es, was die Magie bewirkt. Deklarieren Sie die Funktion, die die Textersetzungen übernimmt:

@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)
}

Stellen Sie schließlich textField's autocorrectionTypeauf ein .no, um prädiktiven Text zu entfernen:

passwordText.autocorrectionType = .no

Verwenden passwordValueSie diese Option, um Ihre Anmeldung durchzuführen.

Hoffe es wird jemandem helfen.

AKTUALISIEREN

Es fängt auch eingefügte Werte ab und hat vergessen, sie vorher hinzuzufügen.

Gal Shahar
quelle
2
Super! Netter Hack-Kumpel! Schade, dass iOS uns eher zum Hacken bringt, als sauberere Möglichkeiten zu bieten, um die grundlegendsten Dinge zu tun. Dies sollte die akzeptierte Antwort sein.
Sandpat
9

Die Funktion kann deaktiviert werden, indem ein Inhaltstyp angegeben wird, der weder Benutzername noch Kennwort ist. Wenn der Benutzer beispielsweise eine E-Mail-Adresse eingeben soll, können Sie diese verwenden

usernameTextField?.textContentType = .emailAddress
gebirgsbärbel
quelle
1
Interessanterweise habe ich ein E-Mail-Adressfeld über einem Passwortfeld und das E-Mail-Adressfeld bietet eine automatische Vervollständigung.
Brad Root
1
@BradRoot ändere auch dein Passwortfeld textContentype! Wenn Ihre E-Mail bereits im Schlüsselbund gespeichert ist, werden die Informationen in der Schnellleiste angezeigt. Besser für den Benutzernamen .nickname oder versuchen Sie diesen Code, wenn #available (iOS 10.0, *) {self.passwordTextField.textContentType = UITextContentType.init (rawValue: " ")} else {// Fallback auf frühere Versionen}
Sahil
8

Sie können eine Erweiterung für UITextContentType wie folgt hinzufügen

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

Danach können Sie es verwenden

if #available(iOS 10.0, *) {
    passwordField.textContentType = .unspecified
}
Mikhail Zinov
quelle
6

Ein sehr einfacher Ansatz in ios11 hat bei mir funktioniert. Angenommen, Ihre iboutlets sind usernametextfield und passwordtextfield. Verwenden Sie in der viewDidLoad () -Funktion Ihres Viewcontrollers, die beide Outlest enthält, den folgenden Code

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

Danach wird die Option zum automatischen Ausfüllen von Zubehör nicht mehr angezeigt, wenn Sie auf Ihre Textfelder tippen.

Ammad
quelle
6

als Antwort auf @Gal Shahar Antwort.

iOS 12 erkennt Passwort textFields nach isSecureTextEntryEigenschaft und nicht nur nach textContentTypeEigenschaft.

Umgehen, um den Vorschlag zum automatischen Ausfüllen zu umgehen.

  1. Setzen Sie die isSecureTextEntry Eigenschaft auf false.

self.passwordTextField.secureTextEntry = NO;

  1. Fügen Sie eine UITextField-Delegatenmethode hinzu und aktivieren Sie die isSecureTextEntry Eigenschaft.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField == self.passwordTextField && !self.passwordTextField.secureTextEntry) {
        self.passwordTextField.secureTextEntry = YES;
    }

    return YES;
}

HINWEIS: - Verwenden Sie NICHT dieshouldBeginEditing UITextField-Delegatmethode, da weiterhin Vorschläge zum automatischen Ausfüllen angezeigt werden. Verwenden Sie NICHT dietextFieldDidChange UITextField-Delegatenmethode. Der erste Zeichner wird automatisch gelöscht, da dies nach der Anzeige des ersten Zeichens geschieht. Und 'SecureTextEntry' leert das Feld.

aschfahl
quelle
1
Dies löst nicht nur ein besprochenes Problem, sondern auch das Problem des falschen Lesens einer Tastaturhöhe aus der UIKeyboardWillShowNotification, wenn Sie anfänglich auf das Kennwortfeld tippen. Gute Antwort.
Ekashking
5

Ziel c

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

Das hat bei mir funktioniert.

Matheus Domingos
quelle
3

Das automatische Ausfüllen ist für Benutzer standardmäßig aktiviert. iOS speichert alle Passwörter im Schlüsselbund und stellt sie in Ihren Apps über die Tastatur zur Verfügung. UITextViewund UITextFieldautomatisch für das AutoFill-Passwort berücksichtigt. Sie können deaktivieren, indem Sie einen Inhaltstyp angeben, der weder Benutzername noch Kennwort ist. Wenn die Inhaltstypinformationen jedoch bereits im Schlüsselbund gespeichert sind, werden sie in der Schnellleiste angezeigt. UITextContentTypeDaher ist es besser, einen leeren Typ zuzuweisen, und es wird keine Quickbar angezeigt.

Beispiel:

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

Dies funktionierte für iOS 12 und 10:

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

if (@available(iOS 12, *)) {
    passwordTextField.textContentType = UITextContentTypeOneTimeCode;
}
kein Schicksal
quelle
2

Sie können die Kombination aus Benutzername und Kennwort "deaktivieren", indem Sie textContentTypedem Kennworttextfeld einen Dummy zuweisen .

passwordFormField.textContentType = UITextContentType("dummy")

Dadurch wurde das Schlüsselsymbol sowohl für das Kennwortfeld als auch für das vorangegangene E-Mail-Feld deaktiviert. Auf diese Weise verwenden Sie keinen der vordefinierten Werte und vermeiden, dass in der Tastaturzubehöransicht nicht verwandte Vorschläge angezeigt werden.

Miguel Cabeça
quelle
Funktioniert dies immer noch mit der neuesten iOS 12 Beta für Sie?
Pfandrade
Nein, tut es nicht. Unter iOS 12 wird dieses Feld als neues Kennwortfeld erkannt und ein neues sicheres Kennwort vorgeschlagen (neue iOS 12-Funktion). Ich möchte dieses Verhalten in meinem Fall tatsächlich, daher markiere ich dieses Kennwortfeld mit dem neuen iOS 12 newPasswordUITextContentType. Ich weiß jedoch nicht, wie ich dieses neue Verhalten vermeiden soll.
Miguel Cabeça
Verwenden Sie für iOS 12 Beta Folgendes: textContentType = UITextContentType.oneTimeCode. Dann hat es nicht den Schlüsselbund auf der Tastatur. Es scheint gut für mich ohne Nebenwirkungen zu funktionieren. Wenn Sie .newPassword verwenden, funktioniert dies ebenfalls. Sie werden jedoch aufgefordert, das Kennwort zu speichern, sobald Sie mit dem Kennwort fertig sind.
Daniel Jones
2

Ziel C-Version:

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
    self.passwordTextField.textContentType = @"";
    self.confirmPasswordTextField.textContentType = @"";
}

wo

#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)
Denis Kutlubaev
quelle
1

Soweit ich weiß, funktioniert die Antwort von Bem in iOS 12 nicht und die Antwort von Gal Shahar berücksichtigt einige Randfälle nicht (z. B. wenn ein Benutzer mehrere Zeichen gleichzeitig löscht). Ich habe dies mit einer IBAction umgangen, sodass ich nicht mehr nach der iOS-Version suchen musste. Ich bin nur ein Anfänger, daher ist dies möglicherweise nicht die "beste" oder effizienteste Antwort, aber für mich war dies am sinnvollsten:

Deaktivieren Sie zunächst "Sichere Texteingabe" im Storyboard oder setzen Sie sie über den Code für Ihr Kennwort UITextField auf "false" / "NO". Dadurch wird verhindert, dass iOS versucht, automatisch zu füllen.

Verknüpfen Sie dann Ihr Passwort UITextField mit einer IBAction. Meins heißt:

  • Die Bearbeitung hat begonnen
  • Die Bearbeitung hat sich geändert
  • Die Bearbeitung wurde beendet

Die von mir geschriebene IBAction-Funktion ermittelt die Unterschiede zwischen dem Startkennwort eines Benutzers und dem, was in das Kennwort UITextField eingegeben wurde, und erstellt anhand dieser Informationen ein neues Kennwort:

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)
    }
}

Konstruktive Kritik wird geschätzt!

Escargot
quelle
1

Sie können hier verschiedene Antworten ausprobieren , die zu dem Schluss führen, dass es wahrscheinlich möglich ist, die Zubehöransicht zu entfernen. Dies hinterlässt jedoch einige Fehler.

Sie könnten möglicherweise versuchen, eine benutzerdefinierte Tastatur nur für Kennwortfelder zu implementieren. Versuchen Sie auch, Vorschläge für Ihr Textfeld zu deaktivieren. Ich denke, das verbirgt auch das accessoryView.

EDIT: Immer noch keine Antwort in Apple-Foren auf die gleiche Frage. Auch dazu konnte ich in der offiziellen UITextFieldDokumentation nichts finden .

Rishabh
quelle
1

Verrücktes Personal passiert in diesem Thema. Ich habe ohne iOS ein Passwort vorgeschlagen, mir aber eine automatische Ausfüllung nur für E-Mails gegeben. Nur wenn jemand es so braucht. Nach verschiedenen Kombinationen und verschiedenen Arten textContentTypehabe ich es gemacht, wie ich wollte.

  1. E-Mail-Textfeld mit iOS-AutoFill schlägt vor, etwas zu sein.
  2. Passwort-Textfeld ohne iOS-System, das mir ein neues Passwort vorschlägt, es aber mit einem Passwort ausfüllt, wenn ich es aus dem E-Mail-Textfeld auswähle.
  3. Passwort-Textfeld für sicheren Eintragstext.

Und mit diesem Code hat es funktioniert. Es spielt keine Rolle, ob Sie haben emailoder usernamees wird Ihnen einen Vorschlag mit dem machen, was Sie brauchen. Daher habe ich die automatische Ausfüllansicht für Zubehör deaktiviert und nur die automatische Ausfüllung in der Symbolleiste der Tastatur belassen.

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
quelle
0
self.passwordTextField.autocorrectionType = NO;

Es scheint nicht zu funktionieren, das Schlüsselbundzeichen ist noch da,

self.passwordTextField.textContentType = UITextContentTypeName;

Der obige Code funktioniert, aber wenn die Benutzer ihr Apple ID-Konto eingerichtet haben, wird der Name der Apple ID auf der Tastatur angezeigt. Sie können ihn nicht deaktivieren, indem Sie autocorrectionType auf No setzen. Sie sind sich nicht sicher, ob Apple diese Funktion zum automatischen Ausfüllen noch verfeinert Im Moment ist es ziemlich fehlerhaft.

Roger Han
quelle
Diese Art der 'Antwort' sollte für den Kommentarbereich reserviert werden, da sie keine tatsächliche Antwort oder keinen Link zu einer Referenzdokumentation von Apple usw. enthält. Willkommen bei SO!
stktrc
Noch keine Lösung. Nichts, was hier aufgelistet ist, hat für mich gut funktioniert.
Zumzum
0

Das hat bei mir funktioniert:

HINWEIS: Versuchen Sie, diesen Code in das Kennwort einzutragen, das Kennwort zu bestätigen (falls zutreffend) UND E-Mail-Textfelder. Ich habe es nicht in das E-Mail-Textfeld eingefügt und es wurde immer noch für die beiden Passwortfelder angezeigt.

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
quelle
1
Dies ist das gleiche wie Bem's Antwort.
Eric Aya
0

Ich denke, alle UITextField textContentType in Form zu setzen UITextContentType("")oder .oneTimeCodeist keine saubere Lösung. Aktivieren / Deaktivieren isSecureTextEntrygibt Ihnen immer noch das gleiche Problem.

@Gal Shahars Antwort ist nett, aber immer noch nicht perfekt. Das maskierte Zeichen ist nicht dasselbe wie das maskierte Zeichen, das im sicheren Eingabetext von Apple verwendet wird. Es sollte das Unicode-Zeichen 'BLACK CIRCLE' (U + 25CF) https://www.fileformat.info/info/unicode/char/25cf/index.htm verwenden

Außerdem wird die Cursorbewegung nicht verarbeitet. Beim Einfügen von Text in die Mitte wird die Cursorposition an das Ende des Textes geändert. Beim Auswählen und Ersetzen von Text erhalten Sie den falschen Wert.

Wenn Sie sich für die Verwendung von benutzerdefiniertem isSecureEntryText entscheiden, um das automatische Ausfüllen des Kennworts zu vermeiden, lautet der folgende Code:

Swift 5 (einfache 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 (KOMPLETTE Version mit Sicherung der letzten Zeichenanimation)

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
quelle
0

Geben Sie hier die Bildbeschreibung ein

Ich habe den Screenshot angehängt. Sie können den Inhaltstyp als Benutzername im Storyboard ändern oder programmgesteuert. Sie können eine Erweiterung für UITextfield erstellen.

func diableAutofill() {
        self.autocorrectionType = .no
        if #available(iOS 11.0, *) {
            self.textContentType = .username
        } else {
            self.textContentType = .init("")
        }
    }
Siddhant
quelle
0

Dank Apple konnte ich mit nativen Methoden keinen Weg finden, als isSecureTextEntry auf YES gesetzt wurde. Der Weg von Gal Shahar ist die einzige Lösung zum Deaktivieren der Option zum automatischen Ausfüllen von Passwörtern. Aber es ist einfacher damit

Ziel c

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

schnell

textField(_:shouldChangeCharactersIn:replacementString:)

delegieren. Und verwenden Sie einfachen Code wie diesen. Deklarieren Sie eine String-Variable, die später unseren echten textField-Inhalt enthält. Meiner ist 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;
    }
Batuhan Altun
quelle