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”发送事件拖到子类单元中。
设置事件监听器:
[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 } }
不要忘记设置代表。