【问题标题】:How do I check when a UITextField changes?如何检查 UITextField 何时更改?
【发布时间】:2015-04-08 07:36:06
【问题描述】:

我正在尝试检查文本字段何时发生变化,这也等同于用于 textView 的函数 - textViewDidChange 到目前为止我已经这样做了:

  func textFieldDidBeginEditing(textField: UITextField) {
        if self.status.text == "" && self.username.text == "" {
            self.topRightButton.enabled = false
        } else {   
            self.topRightButton.enabled = true
        }
    }

哪种方法有效,但只要按下文本字段就会启用topRightButton,我希望仅在实际输入文本时启用它?

【问题讨论】:

    标签: ios swift uitextfield


    【解决方案1】:

    SWIFT

    斯威夫特 4.2

    textfield.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: .editingChanged)
    

    @objc func textFieldDidChange(_ textField: UITextField) {
    
    }
    

    SWIFT 3 和 Swift 4.1

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

    func textFieldDidChange(_ textField: UITextField) {
    
    }
    

    SWIFT 2.2

    textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingChanged)
    

    func textFieldDidChange(textField: UITextField) {
        //your code
    }
    

    目标-C

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

    而textFieldDidChange方法是

    -(void)textFieldDidChange :(UITextField *) textField{
        //your code
    }
    

    【讨论】:

    • 这对我来说崩溃了,我不明白为什么。
    • 检查了多次。代表在 viewDidLoad 中紧接在它之前设置。行动是一个字母一个字母相同。一旦按下键盘按钮,应用程序就会崩溃。编辑:想通了!缺少动作中的分号。我假设它只需要与函数名称相同。
    • @FawadMasud 这现在在带有 XCode 7 的 iOS 9 上的 Swift 2.0 中没有任何作用,它是否已被贬值,或者您知道当前的修复方法吗?
    • @bibscy 是的,您必须遍历视图内的所有文本字段。
    • 对于 Swift 4.2 它:Texttfield.addTarget(self, action: #selector(ViewControllerr.textFieldDidChange(_:)), for: UIControl.Event.editingChanged)
    【解决方案2】:

    您可以在界面生成器中进行此连接。

    1. 在故事板中,单击屏幕顶部的助理编辑器(中间有两个圆圈)。

    2. Ctrl + 单击界面生成器中的文本字段。

    3. 从 EditingChanged 拖动到助手视图中的视图控制器类内部。

    4. 为您的函数命名(例如“textDidChange”)并单击连接。

    【讨论】:

    • 这是一个很好的解决方案,尤其是在处理由单独数据源管理的 tableViewCell 中的 UITextField 时。这种方法允许 viewController 直接响应(因此数据源不必响应和委托操作)。
    • 太棒了 - 一个解决烦人问题的简单方法。您当然可以链接多个文本字段
    • 可能比上面更好的答案,因为消除了添加@objc func。
    • 好主意,我使用事件 DidEndEditing
    • 这是最好的解决方案。谢谢@rmooney!
    【解决方案3】:

    斯威夫特 5.0

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

    及处理方法:

    @objc func textFieldDidChange(_ textField: UITextField) {
    
    }
    

    Swift 4.0

    textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
                              for: UIControlEvents.editingChanged)
    

    及处理方法:

    @objc func textFieldDidChange(_ textField: UITextField) {
    
    }
    

    Swift 3.0

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

    及处理方法:

    func textFieldDidChange(textField: UITextField) { 
    
    }
    

    【讨论】:

      【解决方案4】:

      到目前为止我的处理方式:UITextFieldDelegate

      func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
      {
          // text hasn't changed yet, you have to compute the text AFTER the edit yourself
          let updatedString = (textField.text as NSString?)?.stringByReplacingCharactersInRange(range, withString: string)
      
          // do whatever you need with this updated string (your code)
      
      
          // always return true so that changes propagate
          return true
      }
      

      Swift4 版本

      func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
          let updatedString = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)
          return true
      }
      

      【讨论】:

      • 当文本字段为空且用户单击退格键时,不会调用此方法。
      【解决方案5】:

      斯威夫特 3

       textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(sender:)), for: UIControlEvents.editingChanged)
      

      【讨论】:

        【解决方案6】:

        textField(_:shouldChangeCharactersIn:replacementString:) 在 Xcode 8、Swift 3 中为我工作,如果你想检查每一个按键。

        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        
            // Whatever code you want to run here.
            // Keep in mind that the textfield hasn't yet been updated,
            // so use 'string' instead of 'textField.text' if you want to
            // access the string the textfield will have after a user presses a key
        
            var statusText = self.status.text
            var usernameText = self.username.text
        
            switch textField{
            case self.status:
                statusText = string
            case self.username:
                usernameText = string
            default:
                break
            }
        
            if statusText == "" && usernameText == "" {
                self.topRightButton.enabled = false
            } else {   
                self.topRightButton.enabled = true
            }
        
            //Return false if you don't want the textfield to be updated
            return true
        }
        

        【讨论】:

          【解决方案7】:

          Swift 3.0.1+(其他一些 swift 3.0 的答案不是最新的)

          textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
                                    for: UIControlEvents.editingChanged)
          
          func textFieldDidChange(_ textField: UITextField) {
          
          }
          

          【讨论】:

            【解决方案8】:

            您可以从 UITextFieldDelegate 使用此委托方法。它会随着每个字符的变化而触发。

            (Objective C) textField:shouldChangeCharactersInRange:replacementString:
            (Swift) textField(_:shouldChangeCharactersInRange:replacementString:)
            

            但是,这只会在进行更改之前触发(实际上,只有在您从此处返回 true 时才会进行更改)。

            【讨论】:

            • 这应该怎么写,因为我也尝试过这种方法并得出了相同的解决方案,即只有在激活 textField 后才会更改,而不是在文本实际更改后才更改??
            • 当您实现上述委托方法时,它会在您每次更改文本时触发。你只需要添加这段代码,self.textfield.delegate = self
            • 对我来说,这种方法不起作用,因为您无法检查方法中的文本字段是否为空。主要是因为它根据文本字段是否可以更改返回真/假。因此,事件在文本字段有机会变空之前触发。
            • @LeviRoberts,您在此方法中引用了文本字段。所以你可以检查 textfield.text 是否为空。
            • 你好像不明白。当它为空时,.isEmpty 方法在此方法有机会返回 true 之前不等于 true;告诉应用文本字段应该更改。
            【解决方案9】:

            斯威夫特 4

            符合 UITextFieldDelegate

            func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
                // figure out what the new string will be after the pending edit
                let updatedString = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)
            
                // Do whatever you want here
            
            
                // Return true so that the change happens
                return true
            }
            

            【讨论】:

              【解决方案10】:

              现在 iOS13+ 上提供了 UITextField 委托方法

              optional func textFieldDidChangeSelection(_ textField: UITextField)
              

              【讨论】:

              • 这个方法是关于选择的,而不是实际的文本
              【解决方案11】:

              也许使用 RxSwift ?

              需要

              pod 'RxSwift',    '~> 3.0'
              pod 'RxCocoa',    '~> 3.0'
              

              明显添加进口

              import RxSwift
              import RxCocoa
              

              所以你有一个textfield : UITextField

              let observable: Observable<String?> = textField.rx.text.asObservable()
              observable.subscribe(
                          onNext: {(string: String?) in
                              print(string!)
                      })
              

              你还有其他 3 种方法..

              1. onError
              2. 已完成
              3. onDisposed
              4. onNext

              【讨论】:

              • 要仅在文本字段成为第一响应者时接收真正更改的事件,而不是在文本字段成为第一响应者时,您必须在文本上使用 distinctUntilChanged。
              【解决方案12】:

              斯威夫特 4

              textField.addTarget(self, action: #selector(textIsChanging), for: UIControlEvents.editingChanged)
              
              @objc func textIsChanging(_ textField:UITextField) {
              
               print ("TextField is changing")
              
              }
              

              如果您想在用户完全输入后进行更改(一旦用户关闭键盘或按下回车键就会调用它)。

              textField.addTarget(self, action: #selector(textDidChange), for: UIControlEvents.editingDidEnd)
              
               @objc func textDidChange(_ textField:UITextField) {
              
                     print ("TextField did changed") 
               }
              

              【讨论】:

                【解决方案13】:
                txf_Subject.addTarget(self, action:#selector(didChangeFirstText), for: .editingChanged)
                
                @objc func didChangeText(textField:UITextField) {
                    let str = textField.text
                    if(str?.contains(" "))!{
                        let newstr = str?.replacingOccurrences(of: " ", with: "")
                        textField.text = newstr
                    }
                }
                
                @objc func didChangeFirstText(textField:UITextField) {
                    if(textField.text == " "){
                        textField.text = ""
                    }
                }
                

                【讨论】:

                  【解决方案14】:

                  您应该按照以下步骤操作:

                  1. 对文本字段进行 Outlet 引用
                  2. 将UITextFieldDelegate 分配给控制器类
                  3. 配置你的TextField.delegate
                  4. 实现您需要的任何功能

                  示例代码:

                  import UIKit
                  
                  class ViewController: UIViewController, UITextFieldDelegate {
                  
                      @IBOutlet var yourTextFiled : UITextField!
                  
                      override func viewDidLoad() {
                          super.viewDidLoad()
                  
                          yourTextFiled.delegate = self
                      }
                  
                  
                      func textFieldDidEndEditing(_ textField: UITextField) {
                          // your code
                      }
                  
                      func textFieldShouldReturn(_ textField: UITextField) -> Bool {
                          // your code
                      }
                  
                      .
                      .
                      .
                  }
                  

                  【讨论】:

                    【解决方案15】:

                    斯威夫特 4.2

                    在 viewDidLoad 中写入

                    // to detect if TextField changed
                    TextField.addTarget(self, action: #selector(textFieldDidChange(_:)),
                                                       for: UIControl.Event.editingChanged)
                    

                    在 viewDidLoad 之外写这个

                    @objc func textFieldDidChange(_ textField: UITextField) {
                        // do something
                    }
                    

                    您可以通过 UIControl.Event.editingDidBegin 或您想要检测的任何内容更改事件。

                    【讨论】:

                      【解决方案16】:

                      这是使用 Swift 3 添加textField text change listener 的方法:

                      将您的班级声明为UITextFieldDelegate

                      override func viewDidLoad() {
                          super.viewDidLoad()
                      
                          textField.delegate = self
                      
                          textField.addTarget(self, action: #selector(UITextFieldDelegate.textFieldShouldEndEditing(_:)), for: UIControlEvents.editingChanged)
                      }
                      

                      然后传统上添加一个 textFieldShouldEndEditing 函数:

                      func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { // do stuff
                              return true 
                      }
                      

                      【讨论】:

                        【解决方案17】:

                        如果您对 SwiftUI 解决方案感兴趣,它对我有用:

                         TextField("write your answer here...",
                                    text: Binding(
                                             get: {
                                                return self.query
                                               },
                                             set: { (newValue) in
                                                self.fetch(query: newValue) // any action you need
                                                        return self.query = newValue
                                              }
                                    )
                          )
                        

                        我不得不说这不是我的主意,我在这个博客中看到它:SwiftUI binding: A very simple trick

                        【讨论】:

                          【解决方案18】:

                          如果无法将 addTarget 绑定到您的 UITextField,我建议您按照上面的建议绑定其中一个,并在 shouldChangeCharactersIn 方法的末尾插入执行代码。

                          nameTextField.addTarget(self, action: #selector(RegistrationViewController.textFieldDidChange(_:)), for: .editingChanged)
                          
                          @objc func textFieldDidChange(_ textField: UITextField) {
                              if phoneNumberTextField.text!.count == 17 && nameTextField.text!.count > 0 {
                                  continueButtonOutlet.backgroundColor = UIColor(.green)
                              } else {
                                  continueButtonOutlet.backgroundColor = .systemGray
                              }
                          }
                          

                          并在 shouldChangeCharactersIn 函数中调用。

                          func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
                          
                              guard let text = textField.text else {
                                  return true
                              }
                              let lastText = (text as NSString).replacingCharacters(in: range, with: string) as String
                          
                              if phoneNumberTextField == textField {
                                  textField.text = lastText.format("+7(NNN)-NNN-NN-NN", oldString: text)
                                  textFieldDidChange(phoneNumberTextField)
                                  return false
                              }
                              return true
                          }
                          

                          【讨论】:

                            【解决方案19】:

                            斯威夫特 4

                            在 viewDidLoad() 中:

                                //ADD BUTTON TO DISMISS KEYBOARD
                            
                                // Init a keyboard toolbar 
                                let toolbar = UIView(frame: CGRect(x: 0, y: view.frame.size.height+44, width: view.frame.size.width, height: 44))
                                toolbar.backgroundColor = UIColor.clear
                            
                                // Add done button
                                let doneButt = UIButton(frame: CGRect(x: toolbar.frame.size.width - 60, y: 0, width: 44, height: 44))
                                doneButt.setTitle("Done", for: .normal)
                                doneButt.setTitleColor(MAIN_COLOR, for: .normal)
                                doneButt.titleLabel?.font = UIFont(name: "Titillium-Semibold", size: 13)
                                doneButt.addTarget(self, action: #selector(dismissKeyboard), for: .touchUpInside)
                                toolbar.addSubview(doneButt)
                            
                                USDTextField.inputAccessoryView = toolbar
                            

                            添加此功能:

                                @objc func dismissKeyboard() {
                                  //Causes the view (or one of its embedded text fields) to resign the first responder status.
                                  view.endEditing(true)
                                }
                            

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 2022-01-16
                              • 1970-01-01
                              • 2015-01-15
                              • 2014-03-12
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多