iPhone Programming: Max Length Text Field

So one of the first things I needed to do in an iPhone application was limit the amount of characters that a user can enter into a UITextField. At first glance, this seems easy, but it’s actually a little less than straight forward.
First, your containing class needs to implement the UITextFieldDelegate protocol. See my previous post about what protocols and delegates are. In particular, you need to implement the shouldChangeCharactersInRange method:

- (BOOL)textField:(UITextField *)inputTextField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
}

This method gets called when the user enters new text but before the text is actually saved to the field. You return a YES or NO, depending on if you want the new text to be allowed into the field. Basically, you’re checking to see if the next text would be bigger than a given length. If it is, you reject the change. If not, you’re good to go.
Next, you need to check the text field length to see if it’s ok:

if (textField.text.length >= 5 && range.length == 0) {
return NO;
} else {
return YES;
}

Above I’m simply checking to see if the textfields text is bigger than 5. The second part of the expression, the range length checking, is for little more complex scenarios when the range of text you’re changing is more than one character. For now, just check that the range length is 0.
Now, if you have one text field on your screen, you’re done. But what if you have multiple text fields on your form and they all have different max length requirements? Well, the answer turns out to be pretty easy. Simply create a new subclass of the UITextField:

// MaxLengthTextField.h
@interface MaxLengthTextField : UITextField {
int maxLength;
}
@property (nonatomic) int maxLength;
@end
//MaxLengthTextField.m
#import "MaxLengthTextField.h"
@implementation MaxLengthTextField
@synthesize maxLength;
@end

Then, instead of creating instances of UITextField, create instances of MaxLengthTextField. Set the max length of the text field like so:

maxLengthTextFieldInstance.maxLength = 5;

Then in your shouldChangeCharactersInRange method, cast the textField parameter to a MaxLengthTextField type and then check the length using the maxLength property. You’re next method implementation will look like this:

- (BOOL)textField:(UITextField *)inputTextField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
MaxLengthTextField *maxLengthTextField = nil;
if([inputTextField isMemberOfClass:[MaxLengthTextField class]]) {
maxLengthTextField = (MaxLengthTextField *)inputTextField;
}
if ( maxLengthTextField ) {
if (maxLengthTextField.maxLength > 0 &&
maxLengthTextField.text.length >= maxLengthTextField.maxLength &&
range.length == 0)
{
return NO;
} else {
return YES;
}
} else {
return YES;
}
}

And that’s it. You’re done. Well, you could pull the maxLength comparison into the MaxLengthTextField for better encapsulation. That’s left as an exercise to the reader. Enjoy.