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.
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).
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.
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.
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, 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
Download the source for this tutorial here TextMonitor.zip
Until next time, happy iCoding!








14 Comments
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
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.
Hmm thats not helping very much srry.
@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!
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.
This tutorial, and the comments about UITextView were very helpful. Thanks for sharing.
very nice tutorial..
it’s helping me so much
Do you have a video of this tutorial?
I just cant get it work with the UITextField :S want to use it with the tut of the twitter updater
Sean Luan or Darko would like that base 2 to base 10 convertor
Thank you to all of the assist
mucho helpful and very much appreciated. thanks man! now if i could only figure out how to get it to let me change the color of specific words…
Sean,
You’ll have to use a UIWebView for that. Then you can specify HTML instead of plain text and build complex styles however you like.
Tyler
Your step 3 describes dragging from the “Editing Changed” action to “File’s Owner”, but the graphic you display there is what you’d get if you had selected File’s Owner and opened the Connections tab, and then dragged from the Received Action textFieldDidUpdate to the textField on the View and scrolled to “Editing Changed”.
Right now, I’m not getting it to work either way in that the NSLog operation takes off and never stops creating blank entries, so I figure I’m missing a line of code involving “naughtyWord”. (I’m new to C).