I tried using textField:shouldChangeCharactersInRange:replacementString:
without luck. I kept encountering a "bad selector sent to instance" crash when I tried invoking that method.
I also tried raising the Editing events, but I still never reached my breakpoint in my ShouldChangeText override of my UITextFieldDelegate.
I decided to create a helper method which would either invoke the text field's delegate (if exists) or the virtual ShouldChangeCharacters method; and based on that returning true or false, will then change the Text.
I'm using Xamarin.iOS, so my project is in C#, but the logic below could easily be re-written in Objective-C or Swift.
Can be invoked like:
var replacementText = MyTextField.Text + " some more text";
MyTextField.ValidateAndSetTextProgramatically(replacementText);
Extension Helper Class:
/// <summary>
/// A place for UITextField Extensions and helper methods.
/// </summary>
public static class UITextFieldExtensions
{
/// <summary>
/// Sets the text programatically but still validates
/// When setting the text property of a text field programatically (in code), it bypasses all of the Editing events.
/// Set the text with this to use the built-in validation.
/// </summary>
/// <param name="textField">The textField you are Setting/Validating</param>
/// <param name="replacementText">The replacement text you are attempting to input. If your current Text is "Cat" and you entered "s", your replacement text should be "Cats"</param>
/// <returns></returns>
public static bool ValidateAndSetTextProgramatically(this UITextField textField, string replacementText)
{
// check for existing delegate first. Delegate should override UITextField virtuals
// if delegate is not found, safe to use UITextField virtual
var shouldChangeText = textField.Delegate?.ShouldChangeCharacters(textField, new NSRange(0, textField.Text.Length), replacementText)
?? textField.ShouldChangeCharacters(textField, new NSRange(0, textField.Text.Length), replacementText);
if (!shouldChangeText)
return false;
//safe to update if we've reached this far
textField.Text = replacementText;
return true;
}
}