Episode #71

NSNumberFormatter

9 minutes
Published on June 13, 2013

This video is only available to subscribers. Get access to this video and 586 others.

In this episode I take a look at NSNumberFormatter, which is a useful class for getting various string representations of numbers. We then use this to add live number formatting to a UITextField.

Note: There are a handful of errors in this screencast. Check the comments for a full listing, but I was a bit sloppy with math and ended up not having the correct values. The important thing to take away from this episode is the number formatting. Thanks to Dan in the comments for pointing out these out!

Episode Links

Adding commas to numbers

  NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:@"/"
                                                                                     error:nil];
        NSNumber *freeSpace = attributes[NSFileSystemFreeSize];
        long long space = [freeSpace longLongValue] / (1000 * 1000);

        NSLog(@"Free space: %@ MB", [NSNumberFormatter localizedStringFromNumber:@(space)
                         numberStyle:NSNumberFormatterDecimalStyle]);

This is the easiest method, and doesn't require you to create your own instance of NSNumberFormatter. For more advanced use, like setting a custom locale, you'll have to create your own instance.

Performance with multiple instances

Typically with things like table views & collection views, you'll want to format numbers many times, one for each cell. If all the values are using the same format, you should definitely create the instance once and re-use it, rather than allocating a new object each time.

Formatting Currency with a custom format

        NSNumber *amount = @(-29.42);
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
        [formatter setNegativeFormat:@"(ยค00.0)"];
        NSLocale *locale = [NSLocale currentLocale];
        [formatter setLocale:locale];
        NSLog(@"I have %@ in my wallet", [formatter stringFromNumber:amount]);

Live formatting a UITextField

First we need a variable to hold on to some state for us:


@interface OILAddEntryViewController () {
    BOOL _suppressChangeNotification;
}

Then we need to listen to the text change notification, but only for the text field we're interested in:

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(formatMiles)
                                                 name:UITextFieldTextDidChangeNotification
                                               object:self.milesTextField];

Finally we can format the number and stick it back on the text property of the UITextField. In order to make sure that this set doesn't trigger a notification, we set the flag to YES so we can skip the format on the following notification.

- (void)formatMiles {
    if (_suppressChangeNotification) {
        return;
    }

    NSString *display = self.milesTextField.text;
    display = [display stringByReplacingOccurrencesOfString:@"," withString:@""];
    long long miles = [display longLongValue];
    NSNumber *milesNumber = @(miles);


    _suppressChangeNotification = YES;
    self.milesTextField.text = [NSNumberFormatter localizedStringFromNumber:milesNumber
                                                                numberStyle:NSNumberFormatterDecimalStyle];
    _suppressChangeNotification = NO;
}