Событие изменения текста 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;
}
Ответы
Ответ 1
Из правильного способа сделать изменение текста поля uitext перезвоните:
Я ловлю символы, отправленные в элемент управления 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 и перезагрузить табличное представление по мере необходимости.
Вы можете использовать это и поместить CalcuAndUpdateTextFields в качестве selector
.
Ответ 2
Ответ XenElement находится на месте.
Вышеописанное можно сделать и в построителе интерфейса, щелкнув правой кнопкой мыши на UITextField и перетащив сообщение "Редактирование измененного" на ваш блок подкласса.
![UITextField Change Event]()
Ответ 3
установить слушателя события:
[self.textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
на самом деле слушать:
- (void)textFieldDidChange:(UITextField *)textField {
NSLog(@"text changed: %@", textField.text);
}
Ответ 4
Swift:
yourTextfield.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)
Затем реализуйте функцию обратного вызова:
@objc func textFieldDidChange(textField: UITextField){
print("Text changed")
}
Ответ 5
Как указано здесь: событие изменения текста 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-made".
EDIT:
Я только что нашел другой подход, который, я думаю, может быть лучше:
Это включает функцию Key-Value Observing (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
-scenario это прекрасно работает, если вы добавите этот код, например, в свой 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 "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];
}
Кредит на этот ответ в отношении управления "контекстом": fooobar.com/questions/16419/...
Примечание. Похоже, что во время редактирования UITextField
со встроенной клавиатурой iOS свойство "text" текстового поля не обновляется с каждой новой буквой, напечатанной/удаленной. Вместо этого объект текстового поля обновляется "в целом" после того, как вы отменили первый ответный статус текстового поля.
Ответ 6
Мы можем легко настроить, что из Storyboard
CTRL перетащите @IBAction
и измените событие следующим образом:
![введите описание изображения здесь]()
Ответ 7
Здесь в быстрой версии для того же самого.
textField.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
func textFieldDidChange(textField: UITextField) {
}
Спасибо
Ответ 8
Я решил проблему изменения поведения 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
}
Ответ 9
Проверена версия 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!)
}
Ответ 10
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!)
}
Ответ 11
Для Swift 3.0:
let textField = UITextField()
textField.addTarget(
nil,
action: #selector(MyClass.textChanged(_:)),
for: UIControlEvents.editingChanged
)
используя класс:
class MyClass {
func textChanged(sender: Any!) {
}
}
Ответ 12
Версия 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.
}
Надеюсь, поможет.
Ответ 13
Вы должны использовать уведомление для решения этой проблемы, потому что другой метод будет прослушивать поле ввода не на самом деле, особенно если вы используете китайский метод ввода.
В 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;
}
}
наконец, вы запустите, сделаете.
Ответ 14
Swift 3.1:
Селектор: ClassName.MethodName
cell.lblItem.addTarget(self, action: #selector(NewListScreen.fieldChanged(textfieldChange:)), for: .editingChanged)
func fieldChanged(textfieldChange: UITextField){
}
Ответ 15
Версия 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
}
}
Не забудьте установить делегат.
Ответ 16
С закрытием:
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
}
Ответ 17
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didChangeTextViewText:)
name:UITextFieldTextDidChangeNotification object:nil];
- (void) didChangeTextViewText {
//do something
}
Ответ 18
Это действительно просто с наблюдателем и реактивным быстрым движением (RxCocoa & RxSwift).
Просто подпишитесь на текстовое свойство rx, как показано ниже:
myTextField.rx.text.subscribe { text in
print("UITextFieldTextChangeEvent Text:\(text)")
}.disposed(by: disposeBag)
Ответ 19
Версия Swift 4
Использование наблюдения значения ключа Оповестите объекты об изменениях свойств других объектов.
var textFieldObserver: NSKeyValueObservation?
textFieldObserver = yourTextField.observe(\.text, options: [.new, .old]) { [weak self] (object, changeValue) in
guard let strongSelf = self else { return }
print(changeValue)
}