web-dev-qa-db-fra.com

Comment shouldChangeCharactersInRange fonctionne dans Swift?

J'utilise shouldChangeCharactersInRange comme moyen d'utiliser la recherche de type à la volée.

Cependant, j'ai un problème, shouldChangeCharactersInRange est appelé avant que le champ de texte ne soit mis à jour:

En Objective C, j'ai résolu ce problème en utilisant ci-dessous:

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

    return YES;
}

Cependant, j'ai essayé d'écrire ceci dans Swift:

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
}

La méthode est toujours appelée avant que je reçoive une valeur?

56
Ryan

Swift 4

Cette méthode n'utilise pas 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
    }
}

Remarque. Soyez prudent lorsque vous utilisez un champ de texte sécurisé. 

74
Vyacheslav

stringByReplacingCharactersInRange retourne une nouvelle chaîne, alors que diriez-vous de:

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
}
66
Mike Pollard

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

Bien que la propriété textField.text soit facultative, elle ne peut pas être définie sur nil. Si vous définissez cette option sur nil, la chaîne vide dans UITextField est modifiée. Dans le code ci-dessus, c'est pourquoi textFieldText est défini sur chaîne vide si textField.text est nul (via l'opérateur de coalescence nil ??).

L'implémentation textFieldShouldClear(_:) traite le cas où le bouton vide du champ de texte est visible et exploité.

37
Mobile Dan

Dans Swift 3 cela ressemblerait à ceci:

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
}
10
Andrey Gordeev

Swift 3


Si vous souhaitez pré-traiter les caractères saisis ou collés par l'utilisateur, la solution suivante fonctionne comme un charme

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
}

Trouvez-le ici: https://Gist.github.com/Blackjacx/2198d86442ec9b9b05c0801f4e392047

0
blackjacx