如何检查UITextField何时更改?


290

我正在尝试检查文本字段何时更改,也等同于用于textView的功能- textViewDidChange到目前为止,我已经做到了:

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

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

Answers:


739

迅速

斯威夫特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
}

这让我崩溃了,我不明白为什么。
李维·罗伯茨

1
多次检查。代表设置在它内部之前viewDidLoad。动作是逐字母的一样。按下键盘按钮后,应用程序崩溃。编辑:想通了!缺少动作内的分号。我认为它只必须与函数名称相同。
李维·罗伯茨

@FawadMasud这在带有XCode 7的iOS 9的Swift 2.0中现在不起作用了吗?或者您知道当前的解决方法吗?
科迪·韦弗

1
@bibscy是的,您必须遍历视图内的所有文本字段。
Fawad Masud'3

1
对于Swift 4.2,其:Texttfield.addTarget(self,action:#selector(ViewControllerr.textFieldDidChange(_ :)),用于:UIControl.Event.editingChanged)
Exitare

128

您可以在界面构建器中建立此连接。

  1. 在情节提要中,单击屏幕顶部的助手编辑器(中间两个圆圈)。 选择助理编辑

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

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

  4. 命名您的函数(例如“ textDidChange”),然后单击“连接”。 命名功能


3
这是一个很好的解决方案,尤其是在处理由单独数据源管理的tableViewCell中的UITextField时。这种方法允许viewController直接响应(因此数据源不必响应并委派动作)。
wuf810 '16

1
太好了-一个令人烦恼的问题的简单解决方案。您当然可以链接多个文本字段
杰里米·安德鲁斯

1
可能是一个比上述更好的答案,因为消除了@objc func。
马修·布拉德肖

好主意,我使用事件DidEndEditing
Puji Wahono

这是最好的解决方案。谢谢@rmooney!
乔纳森

63

斯威夫特5.0

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

处理方法:

@objc func textFieldDidChange(_ textField: UITextField) {

}

迅捷4.0

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

处理方法:

@objc func textFieldDidChange(_ textField: UITextField) {

}

斯威夫特3.0

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

处理方法:

func textFieldDidChange(textField: UITextField) { 

}

29

到目前为止,我的处理方式: 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
}

1
当文本字段为空并且用户单击退格键时,将不会调用此方法。
马修·米切尔


7

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

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

func textFieldDidChange(_ textField: UITextField) {

}

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
}

5

斯威夫特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
}

4

您可以从UITextFieldDelegate使用此委托方法。每次角色更改都会触发。

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

但是,此操作仅更改之前进行(实际上,仅当您从此处返回true时才进行更改)。


1
当我也尝试过这种方法并得出仅在激活textField后才更改,而不是在文本实际更改后才更改的相同解决方案时,应如何写呢?

当您实现上述委托方法时,每次您更改文本时都会触发。您只需要添加以下代码,self.textfield.delegate = self
Abubakr Dar

对我来说,此方法行不通,因为您无法检查方法中文本字段是否为空。主要是因为根据IF文本字段可以更改,它返回true / false。因此,该事件在文本字段有机会变空之前触发。
李维·罗伯茨

@LeviRoberts,您可以在此方法内引用文本字段。因此,您可以检查textfield.text是否为空。
Abubakr Dar Dar 2013年5

你似乎不明白。如果为空,则在.isEmpty此方法有机会返回true之前,该方法不等于true;否则,此方法将不等于true。告诉应用程序文本字段应更改。
李维·罗伯茨

3

也许使用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!)
        })

U还有其他3种方法。

  1. onError
  2. onCompleted
  3. onDisposed
  4. onNext

要仅接收实际更改的事件,而不是在textfield成为第一响应者时接收事件,则必须在文本上使用distinctUntilChanged。
RealNmae

1

斯威夫特4

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

@objc func textIsChanging(_ textField:UITextField) {

 print ("TextField is changing")

}

如果您要在用户完全输入后进行更改(一旦用户关闭键盘或按Enter键,它将被调用)。

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

 @objc func textDidChange(_ textField:UITextField) {

       print ("TextField did changed") 
 }

1
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 = ""
    }
}

1

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

  1. 对文本字段进行出口引用
  2. 将UITextFieldDelegate分配给控制器类
  3. 配置yourTextField.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
    }

    .
    .
    .
}

0

这是您可以textField text change listener使用Swift 3添加的方式:

宣布您的课程为 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 
}

0

斯威夫特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或您想要检测的事件来更改事件。


0

万一您对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绑定:一个非常简单的技巧


0

如果无法将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
    }
}

并在调用中应将ChangeCharactersIn函数中。

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
}

-1

迅捷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)
    }

-1

创建新的自定义类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
}

}

出于所有应有的尊重,这是一个可怕的解决方案。他只想检查a UITextField是否更新了它的值-为什么创建一个过于复杂的类来解决这个简单的问题?
Guilherme Matuella

@GuilhermeMatuella这是前端代码,供用户了解是否需要填写该字段。解决相同问题的方法不同。这基本上是我的自定义资产
Muhammad Asyraf
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.