简体   繁体   English

如何检查 UITextField 何时更改?

[英]How do I check when a UITextField changes?

I am trying to check when a text field changes, equivalent too the function used for textView - textViewDidChange so far I have done this:我正在尝试检查文本字段何时更改,与用于 textView 的函数相同 - textViewDidChange到目前为止我已经这样做了:

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

Which kind of works, but the topRightButton is enabled as soon as the text field is pressed on, I want it to be enabled only when text is actually typed in?哪种有效,但是只要按下文本字段就会启用topRightButton ,我希望仅在实际输入文本时才启用它?

SWIFT迅速

Swift 4.2斯威夫特 4.2

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

and

@objc func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 3 & swift 4.1斯威夫特 3 和斯威夫特 4.1

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

and

func textFieldDidChange(_ textField: UITextField) {

}

SWIFT 2.2斯威夫特 2.2

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

and

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

OBJECTIVE-C目标-C

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

and textFieldDidChange method is和 textFieldDidChange 方法是

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

You can make this connection in interface builder.您可以在界面生成器中建立此连接。

  1. In your storyboard, click the assistant editor at the top of the screen (two circles in the middle).在故事板中,单击屏幕顶部的助理编辑器(中间有两个圆圈)。 已选择助理编辑

  2. Ctrl + Click on the textfield in interface builder. Ctrl + 单击界面生成器中的文本字段。

  3. Drag from EditingChanged to inside your view controller class in the assistant view.从 EditingChanged 拖动到助手视图中的视图控制器类内部。 建立连接

  4. Name your function ("textDidChange" for example) and click connect.命名您的函数(例如“textDidChange”)并单击连接。 命名功能

Swift 5.0斯威夫特 5.0

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

and handle method:和处理方法:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 4.0斯威夫特 4.0

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

and handle method:和处理方法:

@objc func textFieldDidChange(_ textField: UITextField) {

}

Swift 3.0斯威夫特 3.0

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

and handle method:和处理方法:

func textFieldDidChange(textField: UITextField) { 

}

The way I've handled it so far: in UITextFieldDelegate到目前为止我处理它的方式:在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 version 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
}

斯威夫特 3

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

textField(_:shouldChangeCharactersIn:replacementString:) worked for me in Xcode 8, Swift 3 if you want to check every single keypress. 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
}

Swift 3.0.1+ (Some of the other swift 3.0 answers are not up to date) Swift 3.0.1+ (其他一些 swift 3.0 答案不是最新的)

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

func textFieldDidChange(_ textField: UITextField) {

}

You can use this delegate method from UITextFieldDelegate.您可以从 UITextFieldDelegate 使用此委托方法。 It fires with every character change.它会随着每个角色的变化而触发。

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

However THIS ONLY FIRES BEFORE a change is made (indeed, a change is only made if you do return true from here).但是,这仅在进行更改之前触发(实际上,仅当您从此处返回 true 时才会进行更改)。

Swift 4斯威夫特 4

Conform to UITextFieldDelegate .符合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
}

Maybe use RxSwift ?也许使用 RxSwift ?

need需要

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

add imports obviously明显添加进口

import RxSwift
import RxCocoa

So u have a textfield : UITextField所以你有一个textfield : UITextField

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

U have other 3 methods..你还有其他3种方法..

  1. onError错误
  2. onCompleted已完成
  3. onDisposed onDisposed
  4. onNext onNext

iOS13+ 现在有一个 UITextField 委托方法可用

optional func textFieldDidChangeSelection(_ textField: UITextField)

Swift 4斯威夫特 4

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

@objc func textIsChanging(_ textField:UITextField) {

 print ("TextField is changing")

}

If you want to make a change once the user has typed in completely (It will be called once user dismiss keyboard or press enter).如果您想在用户完全输入后进行更改(一旦用户关闭键盘或按回车键就会调用它)。

textField.addTarget(self, action: #selector(textDidChange), for: UIControlEvents.editingDidEnd)

 @objc func textDidChange(_ textField:UITextField) {

       print ("TextField did changed") 
 }
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 = ""
    }
}

You should follow this steps:您应该按照以下步骤操作:

  1. Make a Outlet reference to the textfield对文本字段进行 Outlet 引用
  2. AssignUITextFieldDelegate to the controller class将UITextFieldDelegate 分配给控制器类
  3. Configure yourTextField.delegate配置你的TextField.delegate
  4. Implement whatever function you need实现您需要的任何功能

Sample code:示例代码:

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
    }

    .
    .
    .
}

Swift 4.2斯威夫特 4.2

write this in viewDidLoad写在 viewDidLoad

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

write this outside viewDidLoad在 viewDidLoad 外面写这个

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

You could change the event by UIControl.Event.editingDidBegin or what ever you want to detect.您可以通过 UIControl.Event.editingDidBegin 或您想要检测的任何内容更改事件。

This is how you can add a textField text change listener using Swift 3 :这是使用Swift 3添加textField text change listener器的方法:

Declare your class as UITextFieldDelegate将你的类声明为UITextFieldDelegate

override func viewDidLoad() {
    super.viewDidLoad()

    textField.delegate = self

    textField.addTarget(self, action: #selector(UITextFieldDelegate.textFieldShouldEndEditing(_:)), for: UIControlEvents.editingChanged)
}

Then just traditionally add a textFieldShouldEndEditing function:然后只需传统地添加一个 textFieldShouldEndEditing 函数:

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

create new custom class MaterialTextfield.swift 创建新的自定义类MaterialTextfield.swift

class MaterialTextfield: UITextField,UITextFieldDelegate {

var bottomBorder = UIView()
var shouldShowEditing = false

override func awakeFromNib() {

    // Setup Bottom-Border

    self.delegate = self
    self.translatesAutoresizingMaskIntoConstraints = false

    bottomBorder = UIView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
    bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1) // Set Border-Color
    bottomBorder.translatesAutoresizingMaskIntoConstraints = false

    addSubview(bottomBorder)

    bottomBorder.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
    bottomBorder.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
    bottomBorder.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
    bottomBorder.heightAnchor.constraint(equalToConstant: 1).isActive = true // Set Border-Strength

}
@IBInspectable var hasError: Bool = false {
    didSet {
        if (hasError) {
            bottomBorder.backgroundColor = UIColor.red//error color
        } else {
            bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1)//passive color
        }

    }
}
@IBInspectable var showEditing: Bool = false{
    didSet {
        if (showEditing) {
            bottomBorder.backgroundColor = UIColor(rgb: 0x56B5CA)//active color
        } else {
            bottomBorder.backgroundColor = UIColor(rgb: 0xE2DCD1)//passive color
        }

    }

}

func textFieldDidBeginEditing(_ textField: UITextField) {//listen to on edit event
    showEditing = !self.showEditing
}
func textFieldDidEndEditing(_ textField: UITextField) {//listen to on end edit event
    showEditing = !self.showEditing
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {//listen to return button event
    textField.resignFirstResponder() // return button will close keyboard
    return true
}

}

Just in case you are interested in a SwiftUI solution, this it's working for me:万一您对 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
                      }
            )
  )

I have to say it's not my idea, I read it in this blog: SwiftUI binding: A very simple trick不得不说这不是我的主意,我是在这篇博客中看到的: SwiftUI 绑定:一个非常简单的技巧

In case it is not possible to bind the addTarget to your UITextField, I advise you to bind one of them as suggested above, and insert the code for execution at the end of the shouldChangeCharactersIn method.如果无法将 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
    }
}

And in call in shouldChangeCharactersIn func.并在 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
}

You can manage editing either by "shouldchangecharacter" delgate or "begin and end" textfield delegate.您可以通过“shouldchangecharacter”委托或“开始和结束”文本字段委托来管理编辑。 Don't forget to set delegate不要忘记设置委托

I am manage to do this using "did begin and end editing" below.我设法使用下面的“开始和结束编辑”来做到这一点。

//MARK:- TextViewDelegate
extension ViewController: UITextFieldDelegate {
    func textFieldDidEndEditing(_ textField: UITextField) {
        let count = self.tfEmail.text?.count ?? 0
        if textField == self.tfEmail {
            if count == 0{
              //Empty textfield
            }else{
              //Non-Empty textfield
            }
        }
    }
    func textFieldDidBeginEditing(_ textField: UITextField) {
        if textField == self.tfEmail{
            //when user taps on textfield
        }
    }
}

swift 4迅速 4

In viewDidLoad():在 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

Add this function:添加此功能:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM