简体   繁体   中英

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?

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)

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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