Событие изменения текста UITextField - PullRequest
531 голосов
/ 10 августа 2011

Как я могу обнаружить любые изменения текста в текстовом поле?Метод делегата shouldChangeCharactersInRange работает для чего-то, но он не полностью соответствует моим потребностям.Так как, пока это не возвращает ДА, тексты textField не доступны для других методов наблюдателя.

например, в моем коде calculateAndUpdateTextFields не получил обновленный текст, пользователь набрал.

Есть ли у них какой-нибудь способ получить что-то вроде textChanged обработчика событий 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;
}

Ответы [ 19 ]

994 голосов
/ 10 августа 2011

С правильный способ сделать изменение текста в uitext callback :

Я ловлю символы, отправленные в элемент управления UITextField, примерно так:

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

В Objective-C:

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

В Swift:

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

Затем в методе textFieldDidChange вы можете проверить содержимое textField, ипри необходимости перезагрузите табличное представление.

Вы можете использовать это и поместить CalculateAndUpdateTextFields в качестве selector.

370 голосов
/ 05 декабря 2012

Ответ XenElement точен.

Вышесказанное можно сделать и в конструкторе интерфейсов, щелкнув правой кнопкой мыши на UITextField и перетащив событие отправки «Editing Changed» на ваш подкласс.

UITextField Change Event

125 голосов
/ 06 июня 2013

для установки прослушивателя событий:

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

на самом деле слушать:

- (void)textFieldDidChange:(UITextField *)textField {
    NSLog(@"text changed: %@", textField.text);
}
76 голосов
/ 15 марта 2016

Swift:

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

Затем реализуйте функцию обратного вызова:

@objc func textFieldDidChange(textField: UITextField){

print("Text changed")

}
28 голосов
/ 19 февраля 2013

Как указано здесь: Событие изменения текста UITextField , похоже, что с iOS 6 (проверено iOS 6.0 и 6.1) невозможно полностью обнаружить изменения в UITextField объекты просто наблюдая за UITextFieldTextDidChangeNotification.

Кажется, что теперь отслеживаются только те изменения, которые были сделаны непосредственно встроенной клавиатурой iOS. Это означает, что если вы измените свой UITextField объект, просто вызвав что-то вроде этого: myUITextField.text = @"any_text", вы вообще не будете уведомлены о каких-либо изменениях.

Я не знаю, если это ошибка или она предназначена. Похоже, ошибка, так как я не нашел разумного объяснения в документации. Здесь также указано: Событие изменения текста UITextField .

Мое «решение» этого заключается в том, чтобы на самом деле публиковать уведомление самостоятельно для каждого изменения, которое я делаю в UITextField (если это изменение выполняется без использования встроенной клавиатуры iOS). Примерно так:

myUITextField.text = @"I'm_updating_my_UITextField_directly_in_code";

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

[NSNotificationCenter.defaultCenter 
  postNotification:myTextFieldUpdateNotification];

Таким образом, вы на 100% уверены, что получите такое же уведомление при изменении свойства .text вашего UITextField объекта, либо когда вы обновите его «вручную» в своем коде, либо через встроенный клавиатура iOS.

Важно учитывать, что, поскольку это не задокументированное поведение, такой подход может привести к получению 2 уведомлений об одном и том же изменении в вашем UITextField объекте. В зависимости от ваших потребностей (что вы на самом деле делаете, когда меняется UITextField.text), это может быть неудобно для вас.

Несколько иной подход заключается в публикации пользовательского уведомления (то есть с пользовательским именем, отличным от UITextFieldTextDidChangeNotification), если вам действительно нужно знать, было ли это уведомление вашим или "созданным на iOS".

EDIT:

Я только что нашел другой подход, который, я думаю, мог бы быть лучше:

Это включает в себя Наблюдение значения ключа (KVO) функция Objective-C (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA).

По сути, вы регистрируетесь как наблюдатель собственности, и если это свойство изменяется, вы получаете уведомление об этом. «Принцип» очень похож на то, как работает NSNotificationCenter, и является главным преимуществом, заключающимся в том, что этот подход работает автоматически также и в iOS 6 (без какой-либо специальной настройки, например необходимости вручную отправлять уведомления).

Для нашего UITextField -сценария это прекрасно работает, если вы добавите этот код, например, в ваш UIViewController, который содержит текстовое поле:

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

}

Кредит на этот ответ относительно "контекстного" управления: https://stackoverflow.com/a/12097161/2078512

Примечание. Похоже, что когда вы выполняете редактирование UITextField с помощью встроенной клавиатуры iOS, свойство text в текстовом поле не обновляется при вводе каждой новой буквы. / удалены. Вместо этого объект текстового поля обновляется «как единое целое» после того, как вы отказываетесь от статуса первого респондента текстового поля.

25 голосов
/ 22 августа 2016

Мы можем легко настроить это из Storyboard, удерживая CTRL @IBAction и изменить событие следующим образом:

enter image description here

13 голосов
/ 01 октября 2015

Здесь в быстрой версии для того же.

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

func textFieldDidChange(textField: UITextField) {

}

Спасибо

10 голосов
/ 11 ноября 2013

Я решил проблему с изменением поведения shouldChangeChractersInRange. Если вы вернете НЕТ, изменения не будут применены iOS внутренне, вместо этого у вас есть возможность изменить его вручную и выполнить любые действия после изменений.

- (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 голосов
/ 25 апреля 2016

Испытанная версия Swift:

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

Параметры объяснены:

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

Затем добавьте метод, который вы создали выше, в ваш UIViewController:

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

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

}
6 голосов
/ 08 ноября 2017

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

}
...