UITextField文本更改事件

如何检测textField中的任何文本更改? delegate方法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; } 

从正确的方式做uitextfield文本更改回调 :

我发现发送到UITextField控件的字符是这样的:

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

然后在textFieldDidChange:方法中,您可以检查textField的内容,并根据需要重新加载您的表视图。

你可以使用它并把calculateAndUpdateTextFields作为你的selector

XenElement的答案是现货。

以上操作也可以在界面生成器中完成,方法是右键单击UITextField,然后将“Editing Changed”发送事件拖到子类单元中。

UITextField更改事件

设置事件监听器:

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

实际听:

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

迅速:

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

然后,执行回调函数:

 func textFieldDidChange(textField: UITextField){ print("Text changed") } 

如上所述: UITextField文本更改事件 ,似乎从iOS 6 (iOS 6.0和6.1已检查)不可能通过观察UITextFieldTextDidChangeNotification完全检测UITextField对象中的更改。

看来,只有通过内置的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]; 

这样,当您在代码中更改“手动”更新UITextField对象的.text属性或通过内置的iOS键盘时,您将100%确信将收到相同的通知。

考虑到这一点很重要,因为这不是一个记录的行为,这种方法可能会导致收到2个UITextField对象相同更改的通知。 根据你的需要(当你的UITextField.text改变时你实际做了什么),这可能会给你带来不便。

如果您实际需要知道通知是您的还是“iOS制作的”,则稍微不同的方法是发布自定义通知(即,使用除UITextFieldTextDidChangeNotification之外的自定义名称)。

编辑:

我刚刚找到了一种我认为可能会更好的方法:

这包括Objective-C的键值观察(KVO)功能( 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

注意:看起来好像您正在编辑带有内置iOS键盘的UITextField ,文本字段的“text”属性不会随键入/删除的每个新字母而更新。 相反,在您退出文本字段的第一个响应者状态之后,文本字段对象将“作为一个整体”更新。

我们可以从Storyboard轻松配置,按住CTRL拖动@IBAction并更改事件如下:

在这里输入图像描述

在这里快速版本相同。

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

您应该使用通知来解决这个问题,因为另一种方法将听取输入框而不是实际输入,特别是当您使用中文输入法时。 在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; } 

}

最后,你跑了,会完成的。

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeTextViewText:) name:UITextFieldTextDidChangeNotification object:nil]; - (void) didChangeTextViewText { //do something } 

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 } 

斯威夫特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!) } 

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

不要忘记设置代表。