0

Is there something like textFieldDidChange available in Xcode 12 that will run on iOS versions earlier than 13?

I am using this function to read the contents of a UITextField whenever it changes:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard CharacterSet(charactersIn: "0123456789").isSuperset(of: CharacterSet(charactersIn: string)) else { return false } let s: String = textField.text ?? "" print("s = \(s)") return true } 

but the printed output is always one character behind.

For example: When I type in 1 the printed output is s = ". Adding a 2 (the textfield now displays 12) prints s = 1. After a 3 (textfield now contains 123), s = 12. And so on. Always one character behind.

Why is this? (I'm guessing because the character does not become part of the textfield.text until the function returns true.)

This gets the contents:

func textFieldDidChangeSelection(_ textField: UITextField) { let s: String = textField.text ?? "" print("s = \(s)") } 

but it only works with iOS 13.x.

How do I get the contents of a UITextfield whenever it changes for any iOS version?

2
  • You just looking for textDidChange. Take a look at UIKitPlus lib it is much easier to use than pure UIKit Commented Jan 10, 2021 at 19:08
  • I'll check it out. But there must be a way to do it with what is already built in! Commented Jan 11, 2021 at 0:15

3 Answers 3

1

Why is this? (I'm guessing because the character does not become part of the textfield.text until the function returns true.)

Correct, that's also why that method has a "should" in its name - you can veto that change by returning false.

Use code like this

guard let text = textField.text as NSString? else { return false } let newText = text.replacingCharacters(in: range, with: string) 

to get a "preview" of what the content of the field would be if you in fact allow the change to happen by returning true

Sign up to request clarification or add additional context in comments.

3 Comments

thank you! And thank you for answering the first question too!
In the same way, using the very similarly (if not identically) named method in its delegate.
Thank you again. I pulled a lot of my hair out, but finally figured it out: stackoverflow.com/a/64505257/8635708
1

yeah that's correct the character does not become the part of textfied.text until you return true that function

if you want to get all of character in textfield shouldChangeCharacters try this one

let oldText = textField.text! let r = Range(range, in: oldText) let text = oldText.replacingCharacters(in: r, with: string) 

Comments

0

If you added a UITextField in Storyboard, you can add an @IBAction for the Editing Changed event:

@IBAction func textFieldChanged(_ sender: Any) { guard let tf = sender as? UITextField else { return } let s: String = tf.text ?? "" print("s = \(s)") } 

If you want to add it via code, add the action - you'll likely do this in viewDidLoad():

 myTextField.addTarget(self, action: #selector(self.myTextFieldChanged(_:)), for: .editingChanged) 

and add this func to your controller:

@objc func myTextFieldChanged(_ sender: Any) { guard let tf = sender as? UITextField else { return } let s: String = tf.text ?? "" print("s = \(s)") } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.