Greg
Greg

Reputation: 707

How to Detect and Get UITextField Contents (Swift)

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?

Upvotes: 0

Views: 1446

Answers (3)

Gereon
Gereon

Reputation: 17844

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

Upvotes: 1

Havel
Havel

Reputation: 31

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)

Upvotes: 1

DonMag
DonMag

Reputation: 77433

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

Upvotes: 0

Related Questions