I've created a custom input view for entering text into UITextField
. Basically it's just custom designed number pad. I have textfields, on which I've set the inputView property to use my custom created UIView
subclass. In that view I have collection of buttons - from 0-9 and also backspace.
Now I want to change the text of UITextField programmatically when those buttons are tapped. The UITextField
adopts UITextInput
protocol, which in it's turn adopts UIKeyInput
protocol. In that protocol I have all the methods I need, i.e. inserting text into cursor position and deleting text.
The problem is that those methods do not fire UITextField
delegate methods. That is if I have custom validation in textField:shouldChangeCharactersInRange:replacementString:
field for instance, that won't work. I've tried to set the text property of UITextField
directly, but that didn't work also.
What is the right way of inserting text into UITextField
, I mean insert text in a way that all delegate methods would be called?
Set the text of UITextField by calling insertText:
aTextField.insertText(" ")
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With