首页 文章

UITextField文本更改事件

提问于
浏览
479

如何检测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;
}

18 回答

  • 25

    设置事件监听器:

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

    实际听:

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

    关闭:

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

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

    }

    最后,你跑,会完成 .

  • 9

    如上所述:UITextField text change event,似乎 as of iOS 6 (已检查iOS 6.0和6.1)仅通过观察 UITextFieldTextDidChangeNotification 无法完全检测 UITextField 对象中的更改 .

    现在似乎只跟踪由内置iOS键盘直接进行的更改 . 这意味着如果您只是通过调用类似的内容来更改 UITextField 对象: myUITextField.text = @"any_text" ,您将不会收到有关任何更改的通知 .

    我没有在文档中找到任何合理的解释 . 这也在这里说明:UITextField text change event .

    我的"solution"实际上是我自己发布了一个通知,我对我的 UITextField 所做的每一次更改(如果没有使用内置的iOS键盘就完成了更改) . 像这样的东西:

    myUITextField.text = @"I'm_updating_my_UITextField_directly_in_code";
    
    NSNotification *myTextFieldUpdateNotification  = 
      [NSNotification notificationWithName:UITextFieldTextDidChangeNotification
                      object:myUITextField];
    
    [NSNotificationCenter.defaultCenter 
      postNotification:myTextFieldUpdateNotification];
    

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

    重要的是要考虑到,因为这不是记录的行为,这种方法可能会导致收到2个通知,用于 UITextField 对象中的相同更改 . 根据您的需求(当您的 UITextField.text 更改时您实际执行的操作),这可能会给您带来不便 .

    如果您确实需要知道通知是您的还是"iOS-made",那么稍微不同的方法是发布自定义通知(这是使用 UITextFieldTextDidChangeNotification 以外的自定义名称) .

    EDIT:

    我刚刚找到了一种不同的方法,我觉得可能会更好:

    这涉及Objective-C的 Key-Value Observing (KVO) 特征(http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA) .

    基本上,您将自己注册为属性的观察者,如果此属性发生更改,您将收到有关它的通知 . "principle"与 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'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];
    
    }
    

    相信"context"管理层的回答:https://stackoverflow.com/a/12097161/2078512

    注意:似乎在您使用内置iOS键盘编辑 UITextField 的过程中,文本字段的"text"属性不会在每次输入/删除新字母时更新 . 相反,在您重新调整文本字段的第一个响应者状态后,文本字段对象会更新"as a whole" .

  • 12

    Swift 3 Version

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

    希望能帮助到你 .

  • 349

    Swift:

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

    然后,实现回调函数:

    @objc func textFieldDidChange(textField: UITextField){
    
    print("Text changed")
    
    }
    
  • 2

    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!)
    
    }
    
  • 1
    [[NSNotificationCenter defaultCenter] addObserver:self 
    selector:@selector(didChangeTextViewText:) 
    name:UITextFieldTextDidChangeNotification object:nil];
    
    
    
    - (void) didChangeTextViewText {
     //do something
    }
    
  • 2

    XenElement的答案很明显 .

    通过右键单击UITextField并将“Editing Changed”发送事件拖到子类单元,也可以在界面构建器中完成上述操作 .

    UITextField Change Event

  • 8

    我解决了改变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
    }
    
  • 2

    Swift 3.1:

    选择器:ClassName.MethodName

    cell.lblItem.addTarget(self, action: #selector(NewListScreen.fieldChanged(textfieldChange:)), for: .editingChanged)
    
      func fieldChanged(textfieldChange: UITextField){
    
        }
    
  • 3

    proper way to do uitextfield text change call back

    我捕获发送到UITextField控件的字符,如下所示:

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

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

    您可以使用它并将 calculateAndUpdateTextFields 作为 selector .

  • 2

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

    不要忘记设置代理 .

  • 21

    对于Swift 3.0:

    let textField = UITextField()
    
    textField.addTarget(
        nil,
        action: #selector(MyClass.textChanged(_:)),
        for: UIControlEvents.editingChanged
    )
    

    使用类如:

    class MyClass {
        func textChanged(sender: Any!) {
    
        }
    }
    
  • 4

    观察者和反应迅速(RxCocoa&RxSwift)非常简单 .

    只需订阅rx的text属性,如下所示:

    myTextField.rx.text.subscribe { text in
       print("UITextFieldTextChangeEvent Text:\(text)")
    }.disposed(by: disposeBag)
    
  • 0

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

    enter image description here

  • 1

    Swift Version tested:

    //Somewhere in your UIViewController, like viewDidLoad(){ ... }
    self.textField.addTarget(
            self, 
            action: #selector(SearchViewController.textFieldDidChange(_:)),
            forControlEvents: UIControlEvents.EditingChanged
    )
    

    Parameters explained:

    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
    

    Then add the method you created above in your UIViewController:

    //Gets called everytime the text changes in the textfield.
    func textFieldDidChange(textField: UITextField){
    
        print("Text changed: " + textField.text!)
    
    }
    
  • 60

    这里的swift版本相同 .

    textField.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)
    
    func textFieldDidChange(textField: UITextField) {
    
    }
    

    谢谢

相关问题