如何检测textField中的任何文本更改?委托方法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;
}
来自proper way to do uitextfield text change call back:
我捕获发送到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的内容,并根据需要重新加载表视图。
你可以使用它并将calculateAndUpdateTextFields作为你的selector
。
斯威夫特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.0:
let textField = UITextField()
textField.addTarget(
nil,
action: #selector(MyClass.textChanged(_:)),
for: UIControlEvents.editingChanged
)
使用类如:
class MyClass {
func textChanged(sender: Any!) {
}
}
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.
}
希望能帮助到你。
您应该使用通知来解决此问题,因为其他方法将侦听输入框而不是实际输入,尤其是当您使用中文输入法时。在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 4版本
Using Key-Value Observing通知对象有关其他对象属性的更改。
var textFieldObserver: NSKeyValueObservation?
textFieldObserver = yourTextField.observe(\.text, options: [.new, .old]) { [weak self] (object, changeValue) in
guard let strongSelf = self else { return }
print(changeValue)
}
观察者和反应迅速(RxCocoa&RxSwift)非常简单。
只需订阅rx的text属性,如下所示:
myTextField.rx.text.subscribe { text in
print("UITextFieldTextChangeEvent Text:\(text)")
}.disposed(by: disposeBag)
XenElement的答案很明显。
通过右键单击UITextField并将“Editing Changed”发送事件拖到子类单元,也可以在界面构建器中完成上述操作。
设置事件监听器:
[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 text change event,似乎从iOS 6(iOS 6.0和6.1检查),仅通过观察UITextField
无法完全检测UITextFieldTextDidChangeNotification
对象的变化。
现在似乎只跟踪由内置iOS键盘直接进行的更改。这意味着如果你只是通过调用这样的东西来改变你的UITextField
对象:myUITextField.text = @"any_text"
,你根本不会得到任何变化的通知。
我不知道这是一个bug还是故意的。似乎是一个错误,因为我没有在文档中找到任何合理的解释。这也在这里说:UITextField text change event。
我对此的“解决方案”是实际发布我自己对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
更改时您实际执行的操作)这可能会给您带来不便。
如果您确实需要知道通知是您的还是“iOS制作”,那么稍微不同的方法是发布自定义通知(这是使用UITextFieldTextDidChangeNotification
以外的自定义名称)。
编辑:
我刚刚找到了一种不同的方法,我觉得可能会更好:
这涉及Objective-C(http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA)的Key-Value Observing(KVO)特征。
基本上,您将自己注册为属性的观察者,如果此属性发生更改,您会收到有关它的通知。 “原则”非常类似于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”属性不会更新每个键入/删除的新字母。相反,在您重新调整文本字段的第一个响应者状态后,文本字段对象将“作为一个整体”更新。
这里的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!)
}