Событие изменения текста 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 и перетащив событие "редактирование изменено" в ваш подкласс.
установить прослушиватель событий:
[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
и изменить событие следующим образом:
здесь в 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)
}
}
}