Событие изменения текста UITextField

как я могу обнаружить любые изменения текста в текстовом поле? Метод делегата shouldChangeCharactersInRange работает для чего-то, но он не выполнил мою потребность точно. Поскольку до тех пор, пока он не вернет YES, тексты 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 ответов


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

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

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

затем в методе textFieldDidChange: вы можете изучить содержимое текстового поля и при необходимости перезагрузить представление таблицы.

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


ответ XenElement находится на месте.

вышеуказанное можно сделать и в interface builder, щелкнув правой кнопкой мыши по UITextField и перетащив событие "редактирование изменено" в ваш подкласс.

UITextField Change Event


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

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

слушаем:

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

Свифт:

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

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

@objc func textFieldDidChange(textField: UITextField){

print("Text changed")

}

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

похоже, что теперь отслеживаются только те изменения, которые сделаны непосредственно встроенной клавиатурой 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 уведомлениям, полученным за одно и то же изменение в вашем


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

enter image description here


здесь в swift версии для того же.

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

func textFieldDidChange(textField: UITextField) {

}

спасибо


Я решил проблему изменения поведения shouldChangeChractersInRange. Если вы вернете NO, изменения не будут применяться 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
}

проверена версия 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!)

}

Для Swift 3.0:

let textField = UITextField()

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

использование класса как:

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

    }
}

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

}

вы должны использовать уведомление для решения этой проблемы, потому что другой метод будет слушать поле ввода,а не фактический ввод, особенно когда вы используете китайский метод ввода. В viewDidload

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

затем

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

}

наконец, вы бежите, будет сделано.


Swift 3.1:

Селектор: ClassName.MethodName

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

  func fieldChanged(textfieldChange: UITextField){

    }

С закрытия:

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

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

и с помощью

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

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



- (void) didChangeTextViewText {
 //do something
}

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

   }

}

Не забудьте установить делегата.


Swift 3 Версия

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

и получите изменения здесь

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

надеюсь, что это помогает.


это очень просто с observer и reactive swift (RxCocoa & RxSwift).

просто подпишитесь на текстовое свойство rx, как показано ниже:

myTextField.rx.text.subscribe { text in
   print("UITextFieldTextChangeEvent Text:\(text)")
}.disposed(by: disposeBag)

Swift 3

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

            } else {
               print(number)
            }
        }
    }