22

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?

veducm
  • 5,933
  • 2
  • 34
  • 40
kyurkchyan
  • 2,260
  • 2
  • 23
  • 37
  • Add your code please... If you are using setText: of UITextField, the delegate methods will not invoked. – Ryan Jul 15 '14 at 08:59
  • 3
    I think this covers it: http://stackoverflow.com/questions/15140087/uicontroleventeditingchanged-doesnt-get-fired-when-using-settext-of-uitextfield – trojanfoe Jul 15 '14 at 09:04
  • There is no need for code I think, because it's just one line - textField.text = @"myText"; And yes, it doesn't call delegate as I've said in my question, so I ask the question to find workaround. – kyurkchyan Jul 15 '14 at 09:05
  • trojanfoe unfortunately it didn't. I tried the examples, but the delegate methods still do not fire. – kyurkchyan Jul 15 '14 at 09:14
  • OK, well you know the text you are inserting so you should be able to validate it before inserting it, alleviating the need for the delegate. Doesn't sound like a very difficult problem to solve. – trojanfoe Jul 15 '14 at 09:18
  • No, not difficult. BUT! I use custom input control, which should be generic. Not bound to particular text field. I can actually call textField:shouldChangeCharactersInRange:replacementString: manually and if it returns true only then change the text. But I wanted not to intervene into delegate method flow, and simply set and the text and let the platform do the delegate method invoking automatically, as if the text is changed through default keyboard. I know there is better support for keyboards in iOS 8, but I need to do that in iOS 7. – kyurkchyan Jul 15 '14 at 09:27
  • Have you set Delegate of that UITextFields? – Viraj Padsala Jan 19 '16 at 07:19
  • 1
    Have you got any solution to trigger the UITextFieldDelegate methods when setting the text programmatically? I have tried `insertText:` and also `[textFiled sendActionsForControlEvents:UIControlEventEditingChanged];`. Neither of this triggers `textField:shouldChangeCharactersInRange:replacementString:` in iOS 11 – Aravind G S Jan 04 '18 at 14:03

3 Answers3

8

Set the text of UITextField by calling insertText:

aTextField.insertText(" ")
David Lindsay
  • 210
  • 3
  • 12
1

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;
    }
}
Kris Coleman
  • 416
  • 3
  • 11
0
self.textfield.delegate = self;
    [self.textfield addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];

/* Put Your View controller Object instead self when delegate methods are in another class */

/* textfield delagete called when text did view change */

-(void)textFieldDidChange:(UITextField *)textView
{
    if(Condition You want to put)
    {
        //Code
    }
    else
    {
        //Code
    }
}

As par this method you want to make custom Methods too.