iosobjective-cnsnumberformatter

NSNumberFormatter and 'th' 'st' 'nd' 'rd' (ordinal) number endings


Is there a way to use NSNumberFormatter to get the 'th' 'st' 'nd' 'rd' number endings?

EDIT:

Looks like it does not exist. Here's what I'm using.

+(NSString*)ordinalNumberFormat:(NSInteger)num{
    NSString *ending;

    int ones = num % 10;
    int tens = floor(num / 10);
    tens = tens % 10;
    if(tens == 1){
        ending = @"th";
    }else {
        switch (ones) {
            case 1:
                ending = @"st";
                break;
            case 2:
                ending = @"nd";
                break;
            case 3:
                ending = @"rd";
                break;
            default:
                ending = @"th";
                break;
        }
    }
    return [NSString stringWithFormat:@"%d%@", num, ending];
}

Adapted from nickf's answer here Is there an easy way in .NET to get "st", "nd", "rd" and "th" endings for numbers?


Solution

  • Since the question asked for a number formatter, here's a rough one I made.

    //
    //  OrdinalNumberFormatter.h
    //
    
    #import <Foundation/Foundation.h>
    
    
    @interface OrdinalNumberFormatter : NSNumberFormatter {
    
    }
    
    @end
    

    and the implementation:

    //
    //  OrdinalNumberFormatter.m
    //
    
    #import "OrdinalNumberFormatter.h"
    
    
    @implementation OrdinalNumberFormatter
    
    - (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error {
        NSInteger integerNumber;
        NSScanner *scanner;
        BOOL isSuccessful = NO;
        NSCharacterSet *letters = [NSCharacterSet letterCharacterSet];
    
        scanner = [NSScanner scannerWithString:string];
        [scanner setCaseSensitive:NO];
        [scanner setCharactersToBeSkipped:letters];
    
        if ([scanner scanInteger:&integerNumber]){
            isSuccessful = YES;
            if (anObject) {
                *anObject = [NSNumber numberWithInteger:integerNumber];
            }
        } else {
            if (error) {
                *error = [NSString stringWithFormat:@"Unable to create number from %@", string];
            }
        }
    
        return isSuccessful;
    }
    
    - (NSString *)stringForObjectValue:(id)anObject {
        if (![anObject isKindOfClass:[NSNumber class]]) {
            return nil;
        }
    
        NSString *strRep = [anObject stringValue];
        NSString *lastDigit = [strRep substringFromIndex:([strRep length]-1)];
    
        NSString *ordinal;
    
    
        if ([strRep isEqualToString:@"11"] || [strRep isEqualToString:@"12"] || [strRep isEqualToString:@"13"]) {
            ordinal = @"th";
        } else if ([lastDigit isEqualToString:@"1"]) {
            ordinal = @"st";
        } else if ([lastDigit isEqualToString:@"2"]) {
            ordinal = @"nd";
        } else if ([lastDigit isEqualToString:@"3"]) {
            ordinal = @"rd";
        } else {
            ordinal = @"th";
        }
    
        return [NSString stringWithFormat:@"%@%@", strRep, ordinal];
    }
    
    @end
    

    Instantiate this as an Interface Builder object and attach the Text Field's formatter outlet to it. For finer control (such as setting maximum and minimum values, you should create an instance of the formatter, set the properties as you wish and attach it to text field using it's setFormatter: method.

    You can download the class from GitHub (including an example project)