This is part of an ELC Tech Network

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

I’m sure you have seen a Twitter client such as Twittelator Pro or Tweetie 2 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 1337 :)

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 twitlonger.

Advertisement

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 h4×0r5 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, read up on it. 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 :)

Follow me on Twitter

Download the source for this tutorial here TextMonitor.zip

Until next time, happy iCoding!

This entry was posted in Recipes, iPhone Programming Tutorials and tagged , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

11 Comments

  1. Adam
    Posted January 6, 2010 at 9:28 pm | Permalink

    thanks for the great tutorial. but i have one problem. i’m actually using a UITextView for the tweet input instead of a UITextField. the problem is that the “editing changed” event is not part of the UITextView’s options. Any way to make this work? Or is there a ways to make text wrap in a UITextField? Thanks

  2. Posted January 7, 2010 at 9:19 am | Permalink

    For a UITextView, set it’s delegate to your class and implement this method:

    -(void)textViewDidChange:(UITextView *)textView {
    int len = textView.text.length;
    }

    *This is a delegate method of UITextView

    Hope that helps.

  3. Bob
    Posted January 7, 2010 at 3:08 pm | Permalink

    Hmm thats not helping very much srry.

  4. Adam
    Posted January 7, 2010 at 7:55 pm | Permalink

    @Bob
    This is what i’ve done to get it working with a textView:

    -(void)textViewDidChange:(UITextView *)textView {
    int maxChars = 140;
    int charsLeft = maxChars – [tweetMessage.text length];

    if(charsLeft == 0) {
    liveOutputTextView.textColor = [UIColor redColor];
    }

    liveOutputTextView.text = [NSString stringWithFormat:@"%d",charsLeft];
    }

    I’ve also taken out the UIAleart and instead made it simply turn the text red when it’s at 0 or below.

    @brandontreb thanks again for the help!

  5. Posted January 8, 2010 at 2:06 pm | Permalink

    I was playing around and got a version where it will prevent the user from going over the given number of characters.

    In at the top of the view controller header file:
    #define totalChars 140

    For the field did update method in the view controller .m file:
    -(IBAction)fieldDidUpdate:(id)sender {
    UITextField *textField = (UITextField *)sender;

    int remainingChars = totalChars – [textField.text length];
    liveOutputTextView.text = [[NSString alloc] initWithFormat:
    @”You have %d characters remaining.”, remainingChars];

    if ([textField.text length] > totalChars)
    textField.text =
    [textField.text stringByPaddingToLength:totalChars withString:@"." startingAtIndex:0];

    }

    Just a note that this is the same method you can use to make a string longer. The withString argument is just a placeholder that’s used when extending rather than shortening the string.

  6. Posted January 14, 2010 at 8:21 pm | Permalink

    This tutorial, and the comments about UITextView were very helpful. Thanks for sharing.

  7. Posted January 27, 2010 at 8:33 pm | Permalink

    very nice tutorial.. :) it’s helping me so much :)

  8. Posted January 28, 2010 at 1:18 am | Permalink

    Do you have a video of this tutorial?

  9. Bob
    Posted January 29, 2010 at 9:31 am | Permalink

    I just cant get it work with the UITextField :S want to use it with the tut of the twitter updater

  10. Sean McGrail
    Posted February 11, 2010 at 4:33 pm | Permalink

    Sean Luan or Darko would like that base 2 to base 10 convertor

  11. Posted March 10, 2010 at 5:46 am | Permalink

    Thank you to all of the assist

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">