I'm learning iOS development and am having a hard time figuring out the various events for the controls. For a test I have a UITextField where the user is meant to input a string in the format: XXXX-XXXX-XXXX-XXXX
I want to be able to check how long the text in the field is after each entry and see if it needs to have a hyphen appended to it. I've set up my IBAction function for this but when I assign it to the "Value Changed" event it does nothing, it works fine when I set it on the "Editing Did End" but that will only call when the user exits the control.
Edit: Just to add, the "Editing Changed" event causes it to crash too. I assume this is a stack overflow or something where the setting of the text calls the event handler again.
So in short, is there any way to set an event handler for each time the user enters a character in the UITextField?
Take a look at "NBAsYouTypeFormatter" and "NBPhoneNumberUtil". These classes will help you a lot.
dingo sky's answer is good, but in the intrest of helping future people that stumble on this solution, there are a couple problems. Dingo's solution allows you to paste long numeric strings into the field that break the "rules" of the delegate, since it's only using the range location for formatting and length. (you can have more than 12 characters and not have the hyphens).
Simple solution is to calculate the length of the resulting string, and reformat it each time.
An updated version of Dingo's answer is below:
After a bit of research I guess the below solution can add/remove a new string at equal intervals automatically.
Explanation: 1. Inserting a new character
Solution in Swift:
The current accepted answer does not account for copy/pasting into the text field
Instead of using the delegate's "shouldChangeCharactersInRange", connect an IBAction from the text field, with the Text Did Change action. Then add the following code:
This is the right way to do this, because if the user pastes text into the text field, you want to format all pasted text accordingly (not just one character at a time).
Here's my approach that works even when you move the cursor and/or delete ranges of text or even paste valid text in. Basically my approach is to reset the text each time and add in hyphens where appropriate. What makes it complicated is that it also resets the position of the cursor to the right place even if the user moves the cursor to the middle of the string. Unfortunately, there's a lot of cases to consider.
I'll admit, it's ridiculously complicated for such a simple task (definitely could use a major cleanup). Also a bit inefficient, but we're not exactly doing intense computations here. As far as I can tell, it's the most foolproof solution here; I welcome anyone to prove me wrong.
OR: just use this https://github.com/romaonthego/REFormattedNumberField
Be aware the previous answer is woefully inadequate. Heaven forbid your user enter an incorrect digit and dare attempt to delete it! In fairness, the poster noted the code may not work perfectly. But then, it wouldn't even compile, so the buyer beware filter should already be high. If you fix the compile error and try the code, you'll see you can easily end up with input that does not match the poster's stated format.
Here's a solution I've used for restricting a text field to a phone number of the format 123-456-7890. Adjusting for other numeric formats is trivial. Note the use of the passed NSRange. And BTW, rejecting non-digit characters is needed even when using a numeric virtual keyboard since users can still enter non-digits via a hardware keyboard.
One other note. I add the hyphen after the entry of the 4th and 7th digits to make the deleting of digits a bit easier. If you add after the 3rd and 6th digits, you will have to handle the case of deleting the dangling hyphen. The code below avoids that use case.