En utilisant `textField: shouldChangeCharactersInRange:`, comment obtenir le texte comprenant le caractère actuellement tapé?

116

J'utilise le code ci-dessous pour essayer de faire textField2en sorte que le contenu textuel de soit mis à jour pour correspondre à textField1chaque fois que l'utilisateur tapetextField1 .

- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {    
  if (theTextField == textField1){    
     [textField2 setText:[textField1 text]];    
  }
}

Cependant, le résultat que j'observe est que ...

textField2 vaut "12", lorsque textField1 vaut "123"

textField2 est "123", lorsque textField1 est "1234"

... quand ce que je veux c'est:

textField2 est "123", lorsque textField1 est "123"

textField2 est "1234", lorsque textField1 est "1234"

Qu'est-ce que je fais mal?

user265961
la source
8
Juste un rappel, il est incroyablement plus facile de toujours utiliser l' événement "Modification modifiée" . Faites-le simplement glisser dans IB vers une fonction que vous créez.
Fattie
Notez que l'événement de modification de modification ne capture aucun événement de modification de texte généré par programme, par exemple, correction automatique / saisie semi-automatique / remplacement de texte.
shim

Réponses:

272

-shouldChangeCharactersInRangeest appelé avant que le champ de texte ne modifie réellement son texte, c'est pourquoi vous obtenez une ancienne valeur de texte. Pour obtenir le texte après l'utilisation de la mise à jour:

[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];
Vladimir
la source
15
Cela a presque fonctionné pour moi. Si je tapais un caractère, cela fonctionnait. Si j'appuyais sur le bouton de suppression, cela supprimait deux caractères. Pour moi, la suggestion suivante a fonctionné: stackoverflow.com/questions/388237/... Fondamentalement, faites un glisser-déposer de UITextField dans votre code (pour créer une fonction), puis cliquez avec le bouton droit sur votre TextField et faites glisser'n ' drop du cercle pour le "Modification modifiée" à votre nouvelle fonction. (Soupir. Visual Studio me manque parfois ..)
Mike Gledhill
Je pense aussi que c'est une réponse valable, mais pas LA réponse. La meilleure façon d'accomplir ce que vous voulez a été répondu par @tomute
Pedro Borges
5
Ou textFiel.text = (textFiel.text as NSString) .stringByReplacingCharactersInRange (range, withString: string) en Swift
Max
@MikeGledhill Vous pouvez faire la même chose par programmation:[textField addTarget:self action:@selector(textFieldEditingChanged:) forControlEvents:UIControlEventEditingChanged]
Steve Moser
52
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString * searchStr = [textField.text stringByReplacingCharactersInRange:range withString:string];

    NSLog(@"%@",searchStr);
    return YES;
}
btmanikandan
la source
40

Swift 3

Sur la base de la réponse acceptée, les éléments suivants devraient fonctionner dans Swift 3 :

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

    let newString = NSString(string: textField.text!).replacingCharacters(in: range, with: string)

    return true
}

Remarque

Les deux Stringet NSStringont des méthodes appelées replacingCharacters:inRange:withString. Cependant, comme prévu, le premier attend une instance de Range, tandis que le second attend une instance de NSRange. La textFieldméthode déléguée utilise une NSRangeinstance, donc l'utilisation de NSStringdans ce cas.

focorner
la source
replacingCharactersdevrait êtrestringByReplacingCharactersInRange
Alan Scarpa
1
@Alan_s J'ai copié cet extrait directement à partir de mon projet Xcode et cela fonctionnait bien. Utilisez-vous Xcode 8.1 avec une cible vers iOS 10.1?
focorner
25

Au lieu d'utiliser UITextFieldDelegate, essayez d'utiliser l' événement "Editing Changed" de UITextField.

tomute
la source
13

Dans Swift (4), sans NSString(Swift pur):

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

    if let textFieldString = textField.text, let swtRange = Range(range, in: textFieldString) {

        let fullString = textFieldString.replacingCharacters(in: swtRange, with: string)

        print("FullString: \(fullString)")
    }

    return true
}

En extension:

extension UITextField {

    func fullTextWith(range: NSRange, replacementString: String) -> String? {

        if let fullSearchString = self.text, let swtRange = Range(range, in: fullSearchString) {

            return fullSearchString.replacingCharacters(in: swtRange, with: replacementString)
        }

        return nil
    }
}

// Usage:

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

    if let textFieldString = textField.fullTextWith(range: range, replacementString: string) {
        print("FullString: \(textFieldString)")
    }

    return true
}
bauerMusique
la source
8

Version Swift pour cela:

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

    if string == " " {
        return false
    }

    let userEnteredString = textField.text

    var newString = (userEnteredString! as NSString).stringByReplacingCharactersInRange(range, withString: string) as NSString

    print(newString)

    return true
}
ioopl
la source
5

C'est le code dont vous avez besoin,

if ([textField isEqual:self.textField1])
  textField2.text = [textField1.text stringByReplacingCharactersInRange:range withString:string];
Deepak Danduprolu
la source
1

utiliser la garde

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        guard case let textFieldString as NSString = textField.text where
            textFieldString.stringByReplacingCharactersInRange(range, withString: string).length <= maxLength else {
                return false
        }
        return true
    }
ober
la source
0

Ma solution est d'utiliser UITextFieldTextDidChangeNotification.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(copyText:) name:UITextFieldTextDidChangeNotification object:nil];

Ne pas oublier d'appeler [[NSNotificationCenter defaultCenter] removeObserver:self];à la deallocméthode.

Boweidmann
la source