How do I check when a UITextField changes?

2019-01-01 03:09发布

问题:

I am trying to check when a text field changes, equivalent too the function used for textView - textViewDidChange so far I have done this:

  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?

回答1:

SWIFT

textField.addTarget(self, action: \"textFieldDidChange:\", forControlEvents: UIControlEvents.EditingChanged)

Then you can just call your function!

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

SWIFT 2.2

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

and

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

SWIFT 3 & swift 4.1

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

and

func textFieldDidChange(_ textField: UITextField) {

}

Swift 4

@objc func textFieldDidChange(_ textField: UITextField) {

}

OBJECTIVE-C

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

and textFieldDidChange method is

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


回答2:

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). \"Assistant

  2. Ctrl + Click on the textfield in interface builder.

  3. Drag from EditingChanged to inside your view controller class in the assistant view. \"Making

  4. Name your function (\"textDidChange\" for example) and click connect. \"Naming



回答3:

Swift 3.0

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

and handle method:

func textFieldDidChange(textField: UITextField) { 

}

Swift 4.0

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

and handle method:

@objc func textFieldDidChange(_ textField: UITextField) {

}


回答4:

The way I\'ve handled it so far : in UITextViewDelegate

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

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:

Swift 3

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


回答6:

Swift 3.0.1+ (Some of the other swift 3.0 answers are not up to date)

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

func textFieldDidChange(_ textField: UITextField) {

}


回答7:

Swift 4

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


回答8:

You can use this delegate method from 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).



回答9:

textField(_:shouldChangeCharactersIn:replacementString:) worked for me in Xcode 8, Swift 3 if you want to check every single keypress.

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
}


回答10:

Maybe use RxSwift ?

need

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

add imports obviously

import RxSwift
import RxCocoa

So u have a textfield : UITextField

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

U have other 3 methods..

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


回答11:

Swift 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\") 
 }


回答12:

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


回答13:

You should follow this steps:

  1. Make a Outlet reference to the textfield
  2. AssignUITextFieldDelegate to the controller class
  3. Configure yourTextField.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
    }

    .
    .
    .
}


回答14:

This is how you can add a textField text change listener using Swift 3:

Declare your class as 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:

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


回答15:

swift 4

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