Zdarzenie zmiany tekstu UITextField

Jak mogę wykryć zmiany tekstu w polu tekstowym? Metoda delegata shouldChangeCharactersInRange działa do czegoś, ale nie spełniła dokładnie moich potrzeb. Ponieważ dopóki nie zwróci YES, teksty pola tekstowego nie są dostępne dla innych metod obserwatora.

Np. w moim kodzie calculateAndUpdateTextFields nie dostał zaktualizowanego tekstu, użytkownik wpisał.

Jest ich sposobem na uzyskanie czegoś takiego jak textChanged obsługa zdarzeń Java.

- (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;
}
Author: Juan Boero, 2011-08-10

19 answers

From proper way to do UITextField text change call back :

Łapię znaki wysłane do kontrolki UITextField coś takiego:

// Add a "textFieldDidChange" notification method to the text field control.
[textField addTarget:self 
              action:@selector(textFieldDidChange:) 
    forControlEvents:UIControlEventEditingChanged];

Następnie w metodzie textFieldDidChange: możesz sprawdzić zawartość pola tekstowego i w razie potrzeby przeładować widok tabeli.

Możesz użyć tego i umieścić calculateAndUpdateTextFields jako swoje selector.

 932
Author: Daniel G. Wilson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-21 04:37:52

Odpowiedź Xenelementa jest trafna.

Powyższe można zrobić również w interface builder, klikając prawym przyciskiem myszy pole UITextField i przeciągając Zdarzenie" Editing Changed " Wyślij do jednostki podklasy.

Zdarzenie Zmiany UITextField

 345
Author: William T.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-10 15:51:10

Aby ustawić detektor zdarzeń:

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

Do słuchania:

- (void)textFieldDidChange:(UITextField *)textField {
    NSLog(@"text changed: %@", textField.text);
}
 117
Author: asdf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-19 21:53:24

Swift:

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

Następnie zaimplementuj funkcję callback:

@objc func textFieldDidChange(textField: UITextField){

print("Text changed")

}
 59
Author: Juan Boero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-29 20:23:41

Jak stwierdzono tutaj: UITextField zdarzenie zmiany tekstu, wydaje się, że od wersji iOS 6 (sprawdzone iOS 6.0 i 6.1) nie jest możliwe pełne wykrycie zmian w obiektach UITextField tylko przez obserwację UITextFieldTextDidChangeNotification.

Wydaje się, że tylko te zmiany wprowadzone bezpośrednio przez wbudowaną klawiaturę iOS są teraz śledzone. Oznacza to, że jeśli zmienisz swój obiekt UITextField poprzez wywołanie czegoś takiego: myUITextField.text = @"any_text", w ogóle nie zostaniesz powiadomiony o żadnych zmianach.

Nie wiem czy to jest błąd lub jest przeznaczony. Wygląda na błąd, ponieważ nie znalazłem żadnego sensownego wyjaśnienia w dokumentacji. Jest to również podane tutaj: UITextField zdarzenie zmiany tekstu .

Moim "rozwiązaniem" jest to, aby faktycznie opublikować powiadomienie o każdej zmianie, którą wprowadzam do mojego UITextField (Jeśli ta zmiana odbywa się bez użycia wbudowanej klawiatury iOS). Coś takiego:

myUITextField.text = @"I'm_updating_my_UITextField_directly_in_code";

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

[NSNotificationCenter.defaultCenter 
  postNotification:myTextFieldUpdateNotification];

W ten sposób Masz 100% pewność, że otrzymasz to samo powiadomienie po zmianie właściwość .text Twojego obiektu UITextField, gdy aktualizujesz go "ręcznie" w kodzie lub za pomocą wbudowanej klawiatury iOS.

Ważne jest, aby wziąć pod uwagę, że ponieważ nie jest to udokumentowane zachowanie, takie podejście może doprowadzić do otrzymania 2 powiadomień o tej samej zmianie w obiekcie UITextField. W zależności od twoich potrzeb (co faktycznie robisz, gdy zmienisz UITextField.text) może to być dla ciebie niedogodnością.

Nieco innym podejściem byłoby zamieszczenie zwyczaju powiadomienie (o niestandardowej nazwie innej niż UITextFieldTextDidChangeNotification), Jeśli chcesz wiedzieć, czy powiadomienie było twoje, czy "wykonane na iOS".

EDIT:

Właśnie znalazłem inne podejście, które myślę, że może być lepsze:

Dotyczy to obserwacja wartości klucza (KVO) funkcja Objective-C (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA).

Zasadniczo rejestrujesz się jako obserwator nieruchomości i jeśli ta nieruchomość się zmieni, otrzymujesz o tym powiadomienie. "Zasada" jest bardzo podobna do tego, jak działa NSNotificationCenter, będąc główną zaletą, że to podejście działa automatycznie również w systemie iOS 6 (bez żadnych specjalnych poprawek, takich jak konieczność ręcznego publikowania powiadomienia).

Dla naszego UITextField-scenariusz działa to dobrze, jeśli dodasz ten kod na przykład do twojego UIViewController, który zawiera pole tekstowe:

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];

}

Podziękowania dla tej odpowiedzi dotyczącej zarządzania "kontekstem": https://stackoverflow.com/a/12097161/2078512

Uwaga: wydaje się, że gdy jesteś w trakcie edycji UITextField za pomocą wbudowanej klawiatury iOS, właściwość "text" pola tekstowego nie jest aktualizowana przy każdej nowej literce wpisanej/usuniętej. Zamiast tego obiekt pola tekstowego zostanie zaktualizowany "jako całość" po rezygnacji ze statusu pierwszej odpowiedzi w polu tekstowym.

 25
Author: ercolemtar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:49

Możemy łatwo skonfigurować to z Storyboard, CTRL przeciągnij @IBAction i zmień Zdarzenie w następujący sposób:

Tutaj wpisz opis obrazka

 20
Author: bikram sapkota,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-04 15:14:26

Tutaj w wersji swift dla tego samego.

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

func textFieldDidChange(textField: UITextField) {

}

Thanks

 12
Author: Hindu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-01 07:02:12

Rozwiązałem problem zmiany zachowania shouldChangeChractersInRange. Jeśli zwrócisz Nie, zmiany nie będą stosowane przez system iOS wewnętrznie, zamiast tego masz możliwość zmiany ich ręcznie i wykonywania wszelkich działań po wprowadzeniu zmian.

- (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
}
 9
Author: Pauls,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-11 15:30:03

Testowana wersja Swift:

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

Parametry wyjaśnione:

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

Następnie dodaj metodę utworzoną powyżej w swoim UIViewController:

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

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

}
 8
Author: rottenoats,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 07:36:12

Dla Swift 3.0:

let textField = UITextField()

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

Użycie klasy jak:

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

    }
}
 4
Author: pedrouan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-04 16:31:17

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

}
 3
Author: sconewolf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-08 01:24:31

Powinieneś użyć powiadomienia,aby rozwiązać ten problem, ponieważ druga metoda będzie nasłuchiwać pola wejściowego, a nie rzeczywistego wejścia,zwłaszcza gdy używasz chińskiej metody wprowadzania. In viewDidload

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

Then

- (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;
} 

}

W końcu uciekniesz, to się skończy.

 2
Author: HsuChihYung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-25 06:42:25

Swift 3.1:

Selector: ClassName.MethodName

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

  func fieldChanged(textfieldChange: UITextField){

    }
 2
Author: Beyaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-11 11:32:34

Z Zamknięciem:

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

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

I używając

textField.targetAction? = {
 // will fire on text changed
 }
 2
Author: ebohdas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-21 14:46:15
[[NSNotificationCenter defaultCenter] addObserver:self 
selector:@selector(didChangeTextViewText:) 
name:UITextFieldTextDidChangeNotification object:nil];



- (void) didChangeTextViewText {
 //do something
}
 1
Author: PeiweiChen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-04 06:57:28

Wersja Swift 3:

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

   }

}
Nie zapomnij ustawić delegata.
 1
Author: Joseph Francis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-06 02:36:35

Wersja Swift 3

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

I pobierz zmiany tutaj

func textChanges(_ textField: UITextField) {
    let text = textField.text! // your desired text here
    // Now do whatever you want.
}
Mam nadzieję, że to pomoże.
 1
Author: Riajur Rahman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-04 06:58:12

To naprawdę proste z observer i reactive swift (RxCocoa & RxSwift).

Wystarczy zapisać się do właściwości tekstowej rx, jak poniżej:

myTextField.rx.text.subscribe { text in
   print("UITextFieldTextChangeEvent Text:\(text)")
}.disposed(by: disposeBag)
 0
Author: SPatel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-30 05:23:11

Swift 3

@IBAction func textfildChange(sender: UITextField) {
        if let number = sender.text {
            if number.isEmpty {

            } else {
               print(number)
            }
        }
    }
 -1
Author: Rob-4608,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-06 05:49:06