Wie sollteChangeCharactersInRange in Swift funktionieren?


77

Ich verwende shouldChangeCharactersInRange , um die On-the-Fly- Typensuche zu verwenden .

Ich habe jedoch ein Problem, sollte ChangeCharactersInRange aufgerufen werden, bevor das Textfeld tatsächlich aktualisiert wird:

In Ziel C habe ich dies mit den folgenden Schritten gelöst:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];

    return YES;
}

Ich habe jedoch versucht, dies in Swift zu schreiben:

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
    let txtAfterUpdate:NSString = self.projectSearchTxtFld.text as NSString
    txtAfterUpdate.stringByReplacingCharactersInRange(range, withString: string)

    self.callMyMethod(txtAfterUpdate)
    return true
}

Die Methode wird immer noch aufgerufen, bevor ich einen Wert erhalte?

Antworten:


164

Swift 4, Swift 5

Diese Methode wird nicht verwendet NSString

// MARK: - UITextFieldDelegate

extension MyViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField,
                   shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {
        if let text = textField.text,
           let textRange = Range(range, in: text) {
           let updatedText = text.replacingCharacters(in: textRange,
                                                       with: string)
           myvalidator(text: updatedText)
        }
        return true
    }
}

Hinweis. Seien Sie vorsichtig, wenn Sie ein gesichertes Textfeld verwenden.


Während der Eingabe wird ein zusätzliches Zeichen angehängt. Was ist die Ursache dafür?
Sagar Daundkar

@SagarDaundkar posten Sie Ihren Beispieltext
Vyacheslav

@ PrashantTukadiya Ich sagte darüber
Vyacheslav

@Vyacheslav sorry Irgendwelche Abhilfemaßnahmen für meine Frage stackoverflow.com/questions/50266486/…
Prashant Tukadiya

@PrashantTukadiya Ich habe es mit einer Variablen gelöst, die einen "Tipp" -Zustand speichert
Vyacheslav

74

stringByReplacingCharactersInRange Geben Sie eine neue Zeichenfolge zurück. Wie wäre es also mit:

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {
    if let text = textField.text as NSString? {
        let txtAfterUpdate = text.replacingCharacters(in: range, with: string)
        self.callMyMethod(txtAfterUpdate)
    }
    return true
}

3
Das ist merkwürdig, dass wir in NSString konvertieren müssen, während die Verwendung mit Swift-Zeichenfolgen aufgrund unterschiedlicher Argumenttypen nicht funktioniert.
Hola Soja Edu Feliz Navidad

irgendwie ohne das alte zu benutzen NSString?
Martin

@ Martin Ich glaube nicht, dass es eine gibt, die im Vergleich nicht mühsam schmerzhaft ist. NSString <> String-Konvertierungen sind jedoch alles andere als die schlechtesten, da sie gebührenfrei überbrückt sind
Bitwit

Es werden nicht mehr als 2 Zeichen gleichzeitig benötigt
Nupur Sharma

2
Arbeiten Sie nicht in wenigen Sprachen wie Koreanisch. Das koreanische Wort wird nicht durch das Anhängen eines letzten Zeichens vervollständigt. Bei Eingabe von "대한민국" wäre txtAfterUpdate "대한 민구 ㄱ". Zu Ihrer Information für Koreaner.
Mark

41

Schnelle 3 & 4

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let textFieldText: NSString = (textField.text ?? "") as NSString
    let txtAfterUpdate = textFieldText.replacingCharacters(in: range, with: string)
    callMyMethod(txtAfterUpdate)

    return true
}

func textFieldShouldClear(_ textField: UITextField) -> Bool {
    callMyMethod("")
    return true
}

Swift 2.2

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let textFieldText: NSString = textField.text ?? ""
    let txtAfterUpdate = textFieldText.stringByReplacingCharactersInRange(range, withString: string)
    callMyMethod(txtAfterUpdate)

    return true
}

func textFieldShouldClear(textField: UITextField) -> Bool {
    callMyMethod("")
    return true
}

Obwohl die textField.textEigenschaft optional ist, kann sie nicht auf Null gesetzt werden. Das Setzen auf Null wird in eine leere Zeichenfolge geändert UITextField. Im obigen Code wird daher textFieldTextdie Zeichenfolge auf leer gesetzt, wenn sie textField.textnull ist (über den Null-Koaleszenzoperator ??).

Die Implementierung textFieldShouldClear(_:)behandelt den Fall, in dem die Schaltfläche zum Löschen des Textfelds sichtbar ist und auf sie getippt wird.


1
Stellen Sie sicher, dass textFieldText NSString ist, da sonst ein Fehler mit dem Bereich ausgelöst wird. Ich brauchte ein paar Minuten, um es zu lösen. Prost.
Sharukh Mastan

Warum allerdings? Warum können wir die normale Swift String-Klasse nicht verwenden?
Shanakor

11

In Swift 3 würde es so aussehen:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let text: NSString = (textField.text ?? "") as NSString
    let resultString = text.replacingCharacters(in: range, with: string)

    return true
}

0

Swift 3


Wenn Sie die vom Benutzer eingegebenen oder eingefügten Zeichen vorverarbeiten möchten, funktioniert die folgende Lösung wie ein Zauber

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

    let strippedString = <change replacements string so it fits your requirement - strip, trim, etc>

    // replace current content with stripped content
    if let replaceStart = textField.position(from: textField.beginningOfDocument, offset: range.location),
        let replaceEnd = textField.position(from: replaceStart, offset: range.length),
        let textRange = textField.textRange(from: replaceStart, to: replaceEnd) {

        textField.replace(textRange, withText: strippedString)
    }
    return false
}

Finden Sie es hier: https://gist.github.com/Blackjacx/2198d86442ec9b9b05c0801f4e392047


Würde dies nicht vorhandene Zeichen überschreiben, anstatt sie einzufügen? Ich muss das noch ausprobieren, aber afaik wird die shouldChangeCharactersInMethode aufgerufen, bevor der textField-Inhalt geändert wird
fabb

Ja, das stimmt, aber Sie können bereits die neue Zeichenfolge erstellen, die auf das Textfeld festgelegt wird, wenn Sie truein dieser Funktion zurückkehren. Grundsätzlich können Sie mit dem aktuellen und dem neuen Textfeldinhalt tun, was Sie möchten. Außerdem können Sie steuern, ob Sie die Änderung ablehnen möchten. Außerdem können Sie die festgelegte Zeichenfolge ändern. Sie haben hier also die volle Kontrolle.
Blackjacx

0

Diese Funktion wird aufgerufen, wenn Änderungen vorgenommen werden, die Benutzeroberfläche jedoch nicht aktualisiert wird und auf Ihre Auswahl wartet

Sehen Sie sich den zurückgegebenen Bool-Wert an

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
  • Wenn Sie zurückkehren true, bedeutet dies, dass iOS Änderungen akzeptiert (Text, Caret ...).
  • Wenn Sie zurückkehren false, bedeutet dies, dass Sie für all diese Dinge verantwortlich sind

-6

Um den genauen Text in meiner UITextField-Komponente in Swift 3.0 zu erhalten, habe ich Folgendes verwendet:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
   let enteredTxt = textField.text! + string
   doSomethingWithTxt(enteredTxt) //some custom method
}

2
Was ist, wenn der Benutzer ein Zeichen löscht? Sie müssen den Bereich verwenden.
Gabriel.Massana

2
Was ist, wenn sie Zeichen in der Mitte der Zeichenfolge bearbeitet haben? Die Nichtverwendung des Bereichs ist falsch.
Michael Peterson
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.