NSNumberFormatter
Wednesday, June 9, 2010 at 5:45PM Next step for me is to collect information about NSNumberFormatter.
NSNumberFormatter is a subclass of NSFormatter. While it uses CFNumberFormatter, it is not toll-free bridged. A CFNumberFormatterRef is actually a member variable inside NSNumberFormatter. Since Mac OS X 10.4 CFNumberFormatter is internally using ICU.
- (NSString *)stringForObjectValue:(id)obj;
After checking, if the obj is actually an NSNumber (otherwise it simply returns nil). If obj is nil, the -nilSymbol is returned.
Otherwise -doubleValue is requested and checked for a real number.
FP_NAN, the-notANumberSymbolis returnedFP_SUBNORMALorFP_ZEROreturns the-zeroSymbolFP_INFINITEeither returns-negativeInfinitySymbolor-positiveInfinitySymbol.
If the NSNumber is a regular number, CFNumberFormatterCreateStringWithNumber is called with the CFNumberFormatter, which is part of the NSNumberFormatter.
- (NSAttributedString *)attributedStringForObjectValue:(id)obj withDefaultAttributes:(NSDictionary *)attrs;
This method simply calls -stringForObjectValue and applies the following text attributes, if necessary:
obj == niladds the-textAttributesForNilattributesFP_NANadds the-textAttributesForNotANumberattributesFP_SUBNORMALandFP_ZEROare adding the-textAttributesForZeroattributesFP_INFINITEare adding either the-textAttributesForNegativeInfinityor-textAttributesForPositiveInfinity
If the number is a regular number, either -textAttributesForNegativeValues or -textAttributesForPositiveValues are applied.
- (BOOL)getObjectValue:(out id *)obj forString:(NSString *)string errorDescription:(out NSString **)error;
Internally this method uses the following method with a minor parsing change, but returns the -localizedDescription of the NSError and ignores the range.
NSNumberFormatter specific methods
- (BOOL)getObjectValue:(out id *)obj forString:(NSString *)string range:(inout NSRange *)rangep error:(out NSError **)error;
This method reports the used range of the string and an NSError in addition to the usual stuff from NSFormatter. The function behaves differently depending if the behavior is set to 10.0 or 10.4. I'll only discuss the 10.4 behavior here, before 10.4 the parser was not using the ICU library and the parsing was done in code inside the formatter.
- If the string is the
nilSymbol, nil is returned - If the string is the
negativeInfinitySymbol,kCFNumberNegativeInfinity is returned (or[NSDecimalNumber minimumDecimalNumber], ifgeneratesDecimalNumbers is set) - If the string is the
positiveInfinitySymbol,kCFNumberPositiveInfinityis returned (or[NSDecimalNumber maximumDecimalNumber], ifgeneratesDecimalNumbersis set) - If the
decimalSeparatoror thegroupingSeparatoris a non-breaking space (ASCII 160), all spaces from the first occurrence of digits to the last occurrence of digits string are replaced with the non-breaking space. Example: " 1 234.56 " will become " 1?234.56 " with the "?" being the non-breaking space. This seems like an internal adaption for ICU. CFNumberFormatterCreateNumberFromStringis called with the string (limited by the optional range)- If the application using this formatter was linked on 10.6 or later the leftover characters may not contain anything but whitespace Characters, otherwise the detection failed
- If the detection failed, a second try is made with a modified format string for the
CFNumberFormatter. The formatter string is based on the Unicode Technical Standard #35 and stripped down to only contain the symbols 0-9 and "#@.-+%‰¤". Groupings, exponent formatting, pad escape (but not the padding characters, which seems a bug) and subpattern (which also seems to look like a bug) are removed. - If the parsing still fails, the method returns an error
- Otherwise the detected range is updated.
- Then the minimum and maximum range is checked and an error returned if the value is outside of this range.
- At the end an NSDecimalNumber is returned, if -generatesDecimalNumber is set.
- (NSString *)stringFromNumber:(NSNumber *)number;
This is a convenience method. This method returns nil, if number is nil, otherwise it calls -stringForObjectValue:. Therefore it behaves like -stringForObjectValue:, except it never returns the -nilSymbol
- (NSNumber *)numberFromString:(NSString *)string;
This is another convenience method. This method returns nil, if string is nil, otherwise it calls -getObjectValue:forString:errorDescription: and returns the object or nil, if the value couldn't be determined. The error message is ignored.
+ (NSString *)localizedStringFromNumber:(NSNumber *)num numberStyle:(NSNumberFormatterStyle)nstyle;
This is another convenience method. This method returns nil, if string is nil, otherwise it sets the temporarily created formatter behavior to 10.4, the number style to the provided nstyle and returns the -stringForObjectValue:
