Using `textField:shouldChangeCharactersInRange:`, how do I get the text including the current typed character?

Viewed 95478

I'm using the code below to try and have textField2's text content get updated to match textField1's whenever the user types in textField1.

- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {    
  if (theTextField == textField1){    
     [textField2 setText:[textField1 text]];    
  }
}

However, the output I observe is that...

textField2 is "12", when textField1 is "123"

textField2 is "123", when textField1 is "1234"

... when what I want is:

textField2 is "123", when textField1 is "123"

textField2 is "1234", when textField1 is "1234"

What am I doing wrong?

10 Answers

-shouldChangeCharactersInRange gets called before text field actually changes its text, that's why you're getting old text value. To get the text after update use:

[textField2 setText:[textField1.text stringByReplacingCharactersInRange:range withString:string]];

Instead of using the UITextFieldDelegate, try to use "Editing Changed" event of UITextField.

In Swift(4), without NSString (pure Swift):

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

    if let textFieldString = textField.text, let swtRange = Range(range, in: textFieldString) {

        let fullString = textFieldString.replacingCharacters(in: swtRange, with: string)

        print("FullString: \(fullString)")
    }

    return true
}

As an extension:

extension UITextField {

    func fullTextWith(range: NSRange, replacementString: String) -> String? {

        if let fullSearchString = self.text, let swtRange = Range(range, in: fullSearchString) {

            return fullSearchString.replacingCharacters(in: swtRange, with: replacementString)
        }

        return nil
    }
}

// Usage:

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

    if let textFieldString = textField.fullTextWith(range: range, replacementString: string) {
        print("FullString: \(textFieldString)")
    }

    return true
}

This is the code you need,

if ([textField isEqual:self.textField1])
  textField2.text = [textField1.text stringByReplacingCharactersInRange:range withString:string];
Related