iPhone Coding Snippet: Live Character Counter, Word filter, and 1337 Translator For A UITextField

    January 6th, 2010 Posted by: - posted under:Snippets

    I’m sure you have seen a Twitter client such as or count down the characters as you type your Tweet. This is done by responding to the Editing Changed action on a UITextField. Today, I will show you how you can implement this functionality in your application as well as show you some other real world examples of responding to this action. Here are a few of the uses that we will discuss:

    • Countdown of characters allowed – Used when the user is limited by a certain number of characters
    • Word filter – useful in filtering out swear words or other unwanted text
    • Live translator – our example will translate english to :)

    I will create the core code and show you how to modify it slightly to implement the other 2 applications.

    Let’s begin by creating the countdown application.

    1. Start With A View Based Application

    Name the application TextMonitor. I’m giving it this generic name since it will become one of 3 applications.

    View based application

    2. Add You IBOutlets And IBActions

    Before creating my User Interfaces, I always like to declare the IBOutles and IBActions first. That way, I only need to open Interface Builder one time to add the UI components and connect them up. Open TextMonitorViewController.h and add the following code:

    #import
     
    @interface TextMonitorViewController : UIViewController {
            IBOutlet UITextView * liveOutputTextView;
    }
     
    @property (nonatomic, retain) IBOutlet UITextView * liveOutputTextView;
     
    -(void)textFieldDidUpdate:(id)sender;
     
    @end

    Pretty straight forward. We first declare an IBOutlet for the UITextView that we will be updating. It will be used to show our characters remaining. Next, we declare an IBAction that will be called every time the user types a character in the UITextField. Now that our properties and actions have been set up, it’s time to create our interface.

    3. Creating The Interface

    Open up the file TextMonitorViewController.xib in Interface Builder. Drag a UITextField and a UITextView on to the main view. It should look something like this (I change the colors a bit).

    Main View

    Once you have created the view, connect the UITextView to the liveOutputTextView IBOutlet of the File’s Owner object. To do this click on “File’s Owner” in the window titled “TextMonitorViewController.xib”, the click Tools -> Connections Inspector. Drag from the circle that sais liveOutputTextView to your UITextView on the screen and release.

    Next, you will need to connect the textFieldDidUpdate IBOutlet to the Editing Changed action of the UITextField. Click on the UITextField and open the Connection Inspector. Click and drag from the Editing Changed action to the File’s Owner object. The method textFieldDidUpdate should appear, mouse over it and release the click.

    The connections inspector window of File’s Owner should now look like this.

    Connections Inspector

    You may now close Interface Builder and return to the code. The next thing we will do is implement the textFieldDidUpdate method.

    4. The textFieldDidUpdate Method

    This is the method where we will put all of our code. Open up TextMonitorViewController.m and add the following code:

    #import "TextMonitorViewController.h"
     
    @implementation TextMonitorViewController
     
    @synthesize liveOutputTextView;
     
    -(IBAction) textFieldDidUpdate:(id)sender {
            UITextField * textField = (UITextField *) sender;
            int maxChars = 140;
            int charsLeft = maxChars - [textField.text length];
     
            if(charsLeft == 0) {
                    UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"No more characters"
                            message:[NSString stringWithFormat:@"You have reached the character limit of %d.",maxChars]
                            delegate:nil
                             cancelButtonTitle:@"Ok"
                            otherButtonTitles:nil];
                    [alert show];
                    [alert release];
            }
     
            liveOutputTextView.text = [NSString stringWithFormat:@"%d characters remaining.",charsLeft];
    }
     
    - (void)viewDidUnload {
            liveOutputTextView = nil;
    }
     
    - (void)dealloc {
        [super dealloc];
            [liveOutputTextView release];
    }
     
    @end

    The first thing that must be done is to synthesize the liveOutputTextView property. That should be pretty obvious. Let’s examine the code for the textFieldDidUpdate method.

    First, we cast the sender object to a UITextField. This is because we know that a UITextField is invoking this method and passing in a reference to itself. Next, we specify the maximum number of characters allowed (I used the Twitter standard of 140). Following this we simply see how many characters the user has left by subtracting the string length of the user input from the maximum characters allowed. If you wanted to simply count the characters that the user typed, you would not need this additional math, you could simple output [textField.text length].

    I have put in a check to see if the user has typed all 140 characters. If so, I display a message to them notifying them that they don’t have any remaining characters. At this point, I chose not to implement the code to prevent them from typing when they reach the limit (I’ll leave that as a challenge to you) as most Twitter clients allow you to go over the limit and post to .

    Finally, we update the UITextView to notify the user how many characters they have already typed. The final product should look something like this.

    Now that you have seen how to update a UITextView in real time, I will show you how we could alter our textFieldDidUpdate method, to change the program entirely.

    Creating a word filter

    Our word filter will be pretty simple. We will create an NSDictionary where the keys will be swear words and the values will be their replacements. We will then enumerate over the keys of the dictionary and replace them in display text with their values. To do this, replace the code in textFieldDidUpdate with the following code.

    -(IBAction) textFieldDidUpdate:(id)sender {
            UITextField * textField = (UITextField *) sender;
     
            NSDictionary * filteredWords = [NSDictionary dictionaryWithObjectsAndKeys:
                             @"fecal matter",@"poop",
                             @"patooti",@"butt",
                             @"Worst band ever",@"Nickelback",
                             @"nice person",@"douche bag",nil];
            NSString * newString = textField.text;
     
            for(NSString * naughtyWord in filteredWords.allKeys) {
                    NSString * goodWord = [filteredWords objectForKey:naughtyWord];
                    NSLog(@"replacing %@ ",naughtyWord);
                    newString = [newString stringByReplacingOccurrencesOfString:naughtyWord
                            withString:goodWord];
            }
     
            liveOutputTextView.text = newString;
    }

    The result is actually quite amusing. Check out the screenshot below. iCodeBlog is a family friendly iPhone development site :)

    Creating a 1337 Translator

    We can now apply this same concept to create a 1337 translator. The translator will translate the characters as the user types into 1337 speak. (Only the 133737 0f h4x0r5 5p34k 1337). Replace the code in textFieldDidUpdate with the code below to create your translator.

    -(IBAction) textFieldDidUpdate:(id)sender {
            UITextField * textField = (UITextField *) sender;
     
            NSDictionary * l337 = [NSDictionary dictionaryWithObjectsAndKeys:
                                                       @"4",@"a",
                                                       @"|3",@"b",
                                                       @"3",@"e",
                                                       @"1",@"i",
                                                       @"1",@"l",
                                                       @"0",@"o",
                                                       @"|2",@"r",
                                                       @"5",@"s",
                                                       @"7",@"t",
                                                       nil];
            NSString * newString = textField.text;
     
            for(NSString * word in l337.allKeys) {
                    NSString * h4x = [l337 objectForKey:word];
                    newString = [newString stringByReplacingOccurrencesOfString:word withString:h4x];
            }
     
            liveOutputTextView.text = newString;
    }

    For those of you who don’t know what 1337 is, . Check out the result that it produces.

    This translator is actually pretty stupid, but you can see how you could use this to do all sorts of other translations. A good programming challenge for you could be to make a translator that does base 10 to binary.

    So, that concludes our tutorial on live updates based on the user input. I’m sure we will be seeing a whole slew of terrible character counters, word filters, and 1337 translators in the app store after this. Send me the links so that I may partake in the making fun :)

    Download the source for this tutorial here TextMonitor.zip

    Until next time, happy iCoding!