Localizating iPhone Apps – Custom Formatter

From time to time you may need to display some information which is locale specific and we may not be able to do it using NSNumberFormatter and NSDateFormatter. Any example might be displaying telephone numbers in a certain format. In such a case, we can create a custom formatter, which is what this tutorial does.

Introduction
The goal of this article is to create a custom formatter, used to display locale specific data. In this tutorial, I will create a new class to format phone numbers based on the user’s current locale. If the locale is set to “en_US” then the phone number looks like 1(111)111-1111.

NSFormatter
To create a custom formatter, start by creating a new class which inherits from NSFormatter. In Xcode click File -> New File -> NSObject subclass, I have named my file “PhoneNumberFormatter”. The new class you create will inherit from NSObject, simple delete that and inherit from NSFormatter. This is how the header file looks like

#import <UIKit/UIKit.h>

@interface PhoneNumberFormatter : NSFormatter {

NSLocale *locale;
}

@property (nonatomic, copy) NSLocale *locale;

- (NSString *) stringFromPhoneNumber:(NSNumber *)aNumber;

@end

We have a locale property, to keep track of the current user’s locale and a method which takes a NSNumber and returns its string representation.

Since the class inherits from NSFormatter, it needs to override some methods. The three methods that we have to override are stringForObjectValue:(id)anObject, getObjectValue:(id)anObject forString:(NSString *)string errorDescription:(NSString *)error and attributedStringForObjectValue:(id)anObject withDefaultAttributes:(NSDictionary *)attributes. This has been my understanding so far, if I’ am wrong please send me an email. All these methods are really useful in Mac OS X development where we can assign a cell to an NSFormatter object (I have tried to do this in IB for iPhone and it does not work). stringForObjectValue returns NSString object that textually represents the cell’s value and the other two methods are also useful in Mac OS X development and not really helpful in iPhone development. As a result, I will not be talking a lot about these methods.

Lets see how the initWithLocale and stringFromPhoneNumber methods looks like

- (void) initWithLocale {
[super init];

locale = [NSLocale currentLocale];
}

- (NSString *) stringFromPhoneNumber:(NSNumber *)aNumber {

NSString *localeString = [locale localeIdentifier];
NSString *tempStr = [[NSString alloc] initWithString:@""];
NSRange range;
range.length = 3;
range.location = 3;
//Returns the phone number 2032225200 as 1(203)222-5200
if([localeString compare:@"en_US"] == NSOrderedSame) {
NSString *areaCode = [[aNumber stringValue] substringToIndex:3];
NSString *phone1 = [[aNumber stringValue] substringWithRange:range];
NSString *phone2 = [[aNumber stringValue] substringFromIndex:6];

tempStr = [NSString stringWithFormat:@"1(%@)%@-%@", areaCode, phone1, phone2];
}

return tempStr;
}

In the initWithLocale method, we get the current user’s locale and copy it to the internal variable. In stringFromPhoneNumber we write our logic to display the text representation of the NSNumber value, based on the locale. This is a very simple example and I’ am sure there is a better way to parse and display the information.

Let’s also take a look at stringForObjectValue method

- (NSString *) stringForObjectValue:(id)anObject {

if(![anObject isKindOfClass:[NSNumber class]])
return nil;
else
return [self stringFromPhoneNumber:anObject];
}

We first check if the object is kind of NSNumber and if it is we simple pass the control to stringFromPhoneNumber message.

This is how we will use the code in the application

- (void)applicationDidFinishLaunching:(UIApplication *)application {

NSNumber *phoneNumber = [NSNumber numberWithInt:1231231212];
PhoneNumberFormatter *pnf = [[PhoneNumberFormatter alloc] initWithLocale];

NSLog(@"Phone Number: %@ for locale: %@", [pnf stringFromPhoneNumber:phoneNumber], [[pnf locale] localeIdentifier]);

[pnf release];

// Override point for customization after application launch
[window makeKeyAndVisible];
}

The phone number and the locale will be displayed on the debugger window.

Conclusion
Creating a custom formatter, comes in handy when we have to display data like phone numbers and format it according to the user’s current locale. By doing this, we also keep our code clean.

Happy Programming,
iPhone SDK Articles


Attachments

Suggested Readings

Leave a Reply

Your email address will not be published.