Previously stopped "paste" into a UITextField causes "Shake to undo" raise `textField(_:shouldChangeCharactersIn:replacementString:)` with invalid range.

If you handle textField(_:shouldChangeCharactersIn:replacementString:) and return false for a paste operation, once user does and "shake to undo" the provided range is out of bounds of the text field's text. Is this expected?

Here is a sample code that simply limits the input to 5 characters:

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        textField.delegate = self
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        let text = textField.text ?? ""
        let currentString = text as NSString
        
        let newString = currentString.replacingCharacters(in: range, with: string)
        
        return newString.count < 5
    }
}

Steps to reproduce a the crash:

UsernameTextFieldShake[40533:8359309] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString replaceCharactersInRange:withString:]: Range or index out of bounds'
  1. Type "test"
  2. Copy the text
  3. Paste the text at the end of the text field's text
  4. The paste will not be allowed as it is above 5 length.
  5. Shake the device
  6. Press undo
  7. Crash, due to let newString = currentString.replacingCharacters(in: range, with: string)

Is there a correct way to guard agains this "rogue" range? Is this range expected to be provided to the textField(_:shouldChangeCharactersIn:replacementString:), one might think because the previous handling returned false that the undo should happen on the previous accepted command (which was at step 1)

Thank you for the responses.

Previously stopped "paste" into a UITextField causes "Shake to undo" raise `textField(_:shouldChangeCharactersIn:replacementString:)` with invalid range.
 
 
Q