1

My goal here is to format the text as the user is typing

I am not completely sure how to use the

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, 
replacementString string: String) -> Bool {   } 

I have tried several posibilities with this and the closer that I could get to what I want was the answer for this thread:

extension MyViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField,
                   shouldChangeCharactersIn range: NSRange,
                   replacementString string: String) -> Bool {
        if let text = textField.text,
           let textRange = Range(range, in: text) {
           let updatedText = text.replacingCharacters(in: textRange,
                                                       with: string)
           myvalidator(text: updatedText)
        }
        return true
    }
}

I got really close to what I need. I can get the console to print the entered text and the new text for example

Input: 498746454
Console: 
$ 0
4$ 4
49$ 49
498$ 498
4987$ 4 987
49874$ 49 874
498746$ 498 746
4987464$ 4 987 464
49874645$ 49 874 645

that's where my first problem is, because output is 1 character behind than the input in the textfield

How can I get it to change exactly when the text is inputed??

And my second question is how do I get it to display on the textfield??

This is the code I am using:

    func myvalidator(text: String){
        print(text)
    }
    func textField(_ textField: UITextField,shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if let text = amount.text,
           let textRange = Range(range, in: text) {
            let updatedText = amount.text!.replacingCharacters(in: textRange, with: "$ \((amount.text! as NSString).doubleValue.formattedWithSeparator)")
           myvalidator(text: updatedText)
        }
        return true
    }

I did my research here, here, and here and several threads other but the answer either give me similar problems or are outdated for Swift 5

  • First, I personally decouple validation (done in `shouldChangeCharactersIn`) from formatting (which I’d do in the “editing changed” event). Second, there are some idiosyncratic formatting issues associated with decimal numbers, so perhaps you can clarify precisely what sort of input/formatting you need, as your example is ambiguous. Third, 99% of the Stack Overflow solutions I see do not properly handle the text position properly (when updating text, make sure you first capture the text position, figure out where the equivalent text position is in the new string, etc.). – Rob May 25 '20 at 07:01
  • Hello, I don't see any documentation of the “editing changed” event, are you saying I should create the custom function? Ans second the input the user does is just numbers, but I need that as the user is typing the input to be formatted as: $_#_###_###.00 with _ being the thousand separators – Allanguzmanf May 25 '20 at 07:06
  • Re [editing changed](https://developer.apple.com/documentation/uikit/uicontrol/event/1618241-editingchanged), you can either add it programmatically like Chris illustrated below (though, I would, not use `changedCharacters` like he suggested and instead call it `editingChanged` or `didEditingChanged` to avoid confusion), or right in IB you can control-drag from the “Editing changed” outlet in the outlet inspector to your code to create `@IBAction`. – Rob May 25 '20 at 07:31
  • I do have that ```@IBAction``` declared in the, I am actually using it to dynamically change the placeholder of another textField. I tried changing the format of the input there but couldn't figure out how, I kept getting stuck with not being able to type at all any code you would suggest? – Allanguzmanf May 25 '20 at 07:41

2 Answers2

0

To get the current input text, after a character changes, you have to add a custom function to your textField.

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

your function can look like this:

@objc func changedCharacters(textField: UITextField){
    guard let input = textField.text else { return }
    // do with your text whatever you want
}
Chris
  • 227
  • 2
  • 16
0

As per your question, whenever the user types some number you should know the number and updated number should be print in the console. Try below code

func textField(_ textField: UITextField,shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
    let updatedText = newString + "$ \(String(describing: Double(newString) ?? 0.0))"
    myvalidator(text: updatedText)
    return true
}

replace your delegate with above one, you should know that whenever new character you type this delegate helps you to display that character in your textField or not. Last Parameter of this delegate string contains a character user typed recently.