web-dev-qa-db-fra.com

Événement de modification de texte UITextField

Comment détecter les modifications de texte dans un champ de texte? La méthode déléguée shouldChangeCharactersInRange fonctionne pour quelque chose, mais elle ne répondait pas exactement à mes besoins. Puisque jusqu'à ce qu'il retourne YES, les textes textField ne sont pas disponibles pour les autres méthodes d'observation.

par exemple. dans mon code calculateAndUpdateTextFields n'a pas reçu le texte mis à jour, l'utilisateur a tapé.

Est-ce un moyen d'obtenir quelque chose comme textChanged Java gestionnaire d'événements.

- (BOOL)textField:(UITextField *)textField 
            shouldChangeCharactersInRange:(NSRange)range 
            replacementString:(NSString *)string 
{
    if (textField.tag == kTextFieldTagSubtotal 
        || textField.tag == kTextFieldTagSubtotalDecimal
        || textField.tag == kTextFieldTagShipping
        || textField.tag == kTextFieldTagShippingDecimal) 
    {
        [self calculateAndUpdateTextFields];

    }

    return YES;
}
538
karim

De manière correcte de changer le texte de uitextfield, rappeler :

J'attrape les caractères envoyés à un contrôle UITextField à peu près comme ceci:

// Add a "textFieldDidChange" notification method to the text field control.

En Objective-C:

[textField addTarget:self 
              action:@selector(textFieldDidChange:) 
    forControlEvents:UIControlEventEditingChanged];

En rapide:

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

Ensuite, dans la méthode textFieldDidChange, vous pouvez examiner le contenu du champ textField et recharger la vue tabulaire si nécessaire.

Vous pouvez l'utiliser et mettre CalculateAndUpdateTextFields comme votre selector.

1004
Daniel G. Wilson

La réponse de XenElement est parfaite.

Les opérations ci-dessus peuvent également être effectuées dans le générateur d'interface en cliquant avec le bouton droit de la souris sur UITextField et en faisant glisser l'événement d'envoi "Modification modifiée" vers votre unité de sous-classe.

UITextField Change Event

373
William T.

pour définir l'écouteur d'événement:

[self.textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];

réellement écouter:

- (void)textFieldDidChange:(UITextField *)textField {
    NSLog(@"text changed: %@", textField.text);
}
126
asdf

Swift:

yourTextfield.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)

Ensuite, implémentez la fonction de rappel:

@objc func textFieldDidChange(textField: UITextField){

print("Text changed")

}
77
Juan Boero

Comme indiqué ici: événement de modification de texte UITextField , il semble que à partir d'iOS 6 (iOS 6.0 et 6.1 cochée) impossible de détecter complètement les changements dans les objets UITextField simplement en observant le UITextFieldTextDidChangeNotification.

Il semble que seules les modifications apportées directement par le clavier iOS intégré soient désormais suivies. Cela signifie que si vous modifiez votre objet UITextField simplement en invoquant quelque chose comme ceci: myUITextField.text = @"any_text", vous ne serez pas averti du moindre changement.

Je ne sais pas si c'est un bug ou si c'est prévu. Cela ressemble à un bogue puisque je n’ai trouvé aucune explication raisonnable dans la documentation. Ceci est également indiqué ici: événement de modification de texte UITextField .

Ma "solution" consiste à poster une notification par moi-même pour chaque modification apportée à mon UITextField (si cette modification est effectuée sans utiliser le clavier iOS intégré). Quelque chose comme ça:

myUITextField.text = @"I'm_updating_my_UITextField_directly_in_code";

NSNotification *myTextFieldUpdateNotification  = 
  [NSNotification notificationWithName:UITextFieldTextDidChangeNotification
                  object:myUITextField];

[NSNotificationCenter.defaultCenter 
  postNotification:myTextFieldUpdateNotification];

De cette façon, vous êtes sûr à 100% que vous recevrez la même notification lorsque vous modifiez la propriété .text de votre objet UITextField, que vous le mettiez à jour "manuellement" dans votre code ou par le biais du programme intégré. dans le clavier iOS.

Étant donné qu'il ne s'agit pas d'un comportement documenté, il est important de noter que cette approche peut conduire à 2 notifications reçues pour le même changement dans votre objet UITextField. En fonction de vos besoins (ce que vous faites réellement lorsque votre UITextField.text change) cela pourrait être un inconvénient pour vous.

Une approche légèrement différente consisterait à publier une notification personnalisée (c'est-à-dire avec un nom personnalisé autre que UITextFieldTextDidChangeNotification) si vous avez réellement besoin de savoir si la notification était la vôtre ou si elle a été faite par iOS.

EDIT:

Je viens de trouver une approche différente qui, à mon avis, pourrait être meilleure:

Ceci implique la fonctionnalité d'observation de la valeur clé (KVO) (-) de Objective-C ( http://developer.Apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//Apple_ref/doc/uid/10000177-BCICJDHA ).

En gros, vous vous enregistrez en tant qu'observateur d'une propriété et si cette propriété change, vous en êtes averti. Le "principe" est assez similaire au fonctionnement de NSNotificationCenter, étant le principal avantage du fait que cette approche fonctionne automatiquement aussi à partir d'iOS 6 (sans aucun Tweak spécial comme avoir à poster des notifications manuellement).

Pour notre scénario UITextField-, cela fonctionne parfaitement si vous ajoutez ce code à, par exemple, votre UIViewController qui contient le champ de texte:

static void *myContext = &myContext;

- (void)viewDidLoad {
  [super viewDidLoad];

  //Observing changes to myUITextField.text:
  [myUITextField addObserver:self forKeyPath:@"text"
    options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld 
    context:myContext];

}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
change:(NSDictionary *)change context:(void *)context {

  if(context == myContext) {
    //Here you get notified every time myUITextField's "text" property is updated
    NSLog(@"New value: %@ - Old value: %@",
      [change objectForKey:NSKeyValueChangeNewKey],
      [change objectForKey:NSKeyValueChangeOldKey]);
  }
  else 
    [super observeValueForKeyPath:keyPath ofObject:object 
      change:change context:context];

}

Crédit à cette réponse concernant la gestion de "contexte": https://stackoverflow.com/a/12097161/2078512

Remarque: on dirait que lorsque vous êtes en train de modifier un UITextField avec le clavier iOS intégré, la propriété "text" du champ de texte n'est pas mise à jour. à chaque nouvelle lettre tapée/enlevée. Au lieu de cela, l'objet de champ de texte est mis à jour "dans son ensemble" après que vous avez quitté le statut de premier répondant du champ de texte.

28
ercolemtar

Nous pouvons facilement configurer cela à partir de Storyboard, CTRL fait glisser le @IBAction et change l'événement comme suit:

enter image description here

25
bikram sapkota

Ici dans la version Swift pour la même chose.

textField.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)

func textFieldDidChange(textField: UITextField) {

}

Merci

13
Hindu

J'ai résolu le problème en changeant le comportement de shouldChangeChractersInRange. Si vous renvoyez NON, les modifications ne seront pas appliquées par iOS en interne, mais vous aurez la possibilité de les modifier manuellement et d'effectuer toute action après les modifications.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    //Replace the string manually in the textbox
    textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string];
    //perform any logic here now that you are sure the textbox text has changed
    [self didChangeTextInTextField:textField];
    return NO; //this make iOS not to perform any action
}
10
Pauls

Version Swift testée:

//Somewhere in your UIViewController, like viewDidLoad(){ ... }
self.textField.addTarget(
        self, 
        action: #selector(SearchViewController.textFieldDidChange(_:)),
        forControlEvents: UIControlEvents.EditingChanged
)

Paramètres expliqués:

self.textField //-> A UITextField defined somewhere in your UIViewController
self //-> UIViewController
.textFieldDidChange(_:) //-> Can be named anyway you like, as long as it is defined in your UIViewController

Ajoutez ensuite la méthode que vous avez créée ci-dessus dans votre UIViewController:

//Gets called everytime the text changes in the textfield.
func textFieldDidChange(textField: UITextField){

    print("Text changed: " + textField.text!)

}
10
kemicofa

Swift 4

func addNotificationObservers() {

    NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidChangeAction(_:)), name: .UITextFieldTextDidChange, object: nil)

}

@objc func textFieldDidChangeAction(_ notification: NSNotification) {

    let textField = notification.object as! UITextField
    print(textField.text!)

}
6
hgale

Pour Swift 3.0:

let textField = UITextField()

textField.addTarget(
    nil,
    action: #selector(MyClass.textChanged(_:)),
    for: UIControlEvents.editingChanged
)

en utilisant la classe comme:

class MyClass {
    func textChanged(sender: Any!) {

    }
}
5
pedrouan

Version Swift

yourTextField.addTarget(self, action: #selector(YourControllerName.textChanges(_:)), for: UIControlEvents.editingChanged)

Et obtenez les changements ici

func textChanges(_ textField: UITextField) {
    let text = textField.text! // your desired text here
    // Now do whatever you want.
}

J'espère que ça aide.

4
Riajur Rahman

Vous devez utiliser la notification pour résoudre ce problème, car l’autre méthode écoute la zone de saisie et non l’entrée, en particulier lorsque vous utilisez la méthode de saisie en chinois. Dans viewDidload

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFiledEditChanged:)
                                                 name:@"UITextFieldTextDidChangeNotification"
                                               object:youTarget];

ensuite

- (void)textFiledEditChanged:(NSNotification *)obj {
UITextField *textField = (UITextField *)obj.object;
NSString *toBestring = textField.text;
NSArray *currentar = [UITextInputMode activeInputModes];
UITextInputMode *currentMode = [currentar firstObject];
if ([currentMode.primaryLanguage isEqualToString:@"zh-Hans"]) {
    UITextRange *selectedRange = [textField markedTextRange];
    UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
    if (!position) {
        if (toBestring.length > kMaxLength)
            textField.text =  toBestring;
} 

}

enfin, vous courez, allez faire.

2
HsuChihYung

Swift 3.1:

Sélecteur: ClassName.MethodName

  cell.lblItem.addTarget(self, action: #selector(NewListScreen.fieldChanged(textfieldChange:)), for: .editingChanged)

  func fieldChanged(textfieldChange: UITextField){

    }
2
Beyaz

Avec fermeture:

   class TextFieldWithClosure: UITextField {
    var targetAction: (() -> Void)? {
        didSet {
            self.addTarget(self, action: #selector(self.targetSelector), for: .editingChanged)
        }
    }

    func targetSelector() {
        self.targetAction?()
    }
    }

et en utilisant

textField.targetAction? = {
 // will fire on text changed
 }
2
ebohdas

Swift 3 Version:

class SomeClass: UIViewController, UITextFieldDelegate { 

   @IBOutlet weak var aTextField: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        aTextField.delegate = self
        aTextField.addTarget(self, action: #selector(SignUpVC.textFieldDidChange), for: UIControlEvents.editingChanged)        
    }

   func textFieldDidChange(_ textField: UITextField) {

       //TEXT FIELD CHANGED..SECRET STUFF

   }

}

N'oubliez pas de définir le délégué.

1
Joseph Francis
[[NSNotificationCenter defaultCenter] addObserver:self 
selector:@selector(didChangeTextViewText:) 
name:UITextFieldTextDidChangeNotification object:nil];



- (void) didChangeTextViewText {
 //do something
}
1
PeiweiChen

Swift 4 Version

tilisation de l'observation de la valeur clé Informer les objets des modifications apportées aux propriétés d'autres objets.

var textFieldObserver: NSKeyValueObservation?

textFieldObserver = yourTextField.observe(\.text, options: [.new, .old]) { [weak self] (object, changeValue) in
  guard let strongSelf = self else { return }
  print(changeValue)
}
0
Valeriy