如何设置NSNumberFormatter使用"万"(日文/中文10,000标记)显示数字?

mak*_*dad 10 currency nsnumberformatter ios

我的iOS应用会显示不同的货币(美元,日元,澳元,欧元)在不同的本地化(en_US,en_AU,ja_JP等).

对于日语区域/语言(两者都在我的设备上设置),如果我有:

NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
fmt.numberStyle = NSNumberFormatterCurrencyStyle;
fmt.currencyCode = @"JPY";
NSString *labelText = [fmt stringFromNumber:@1000000];
Run Code Online (Sandbox Code Playgroud)

我的标签文字是¥1,000,000.但是,在日文和中文中,可能会写入大于10,000的数字100??,这是我想要的输出.

知道我可以写什么代码100??作为输出吗?

我想避免我的代码中的逻辑块检查locale/region,但我觉得这就是我要反对的东西(例如,使用方法调用fmt.multipler = @(1/10000)将1,000,000除以10,000以获得正确的值).

Fjö*_*nir 4

编辑:此处最新要点:https://gist.github.com/fjolnir/cd72ea39be1476023adf

\n\n

旧线程,但我在寻找解决方案时遇到了它,所以我想我应该发布我的实现。

\n\n

格式化程序本身不处理 \xe5\x86\x86 的放置,但在它之外很容易做到。(如下例所示)

\n\n

下面的预期输出是:

\n\n
2015-03-11 18:00:13.376 LENumberFormatter[82736:3604947] 12\xe5\x84\x843,460\xe4\xb8\x87\xe5\x86\x86\n2015-03-11 18:00:13.377 LENumberFormatter[82736:3604947] 25\xe5\x86\x86\n
Run Code Online (Sandbox Code Playgroud)\n\n

-

\n\n
@import Foundation;\n@import ObjectiveC.message;\n\ntypedef NS_ENUM(NSUInteger, LENumberFormatterAbbreviationStyle) {\n    kLEAbbreviateShort, // 2.5m\n    kLEAbbreviateNormal // 2m 5k\n};\n\n@interface LENumberFormatter : NSNumberFormatter\n@property(nonatomic) BOOL abbreviateLargeNumbers;\n@property(nonatomic) LENumberFormatterAbbreviationStyle abbreviationStyle;\n@end\n\n\n@implementation LENumberFormatter\n- (instancetype)init\n{\n    if((self = [super init])) {\n        self.abbreviationStyle = [self _usingKanjiNumbers]\n                               ? kLEAbbreviateNormal\n                               : kLEAbbreviateShort;\n    }\n    return self;\n}\n\n- (NSString *)stringForObjectValue:(id const)aObj\n{\n    if(!_abbreviateLargeNumbers || ![aObj isKindOfClass:[NSNumber class]])\n        return [super stringForObjectValue:aObj];\n\n    // Copy ourselves to get format the partial digits using the settings on self\n    LENumberFormatter * const partialFormatter = [self copy];\n    partialFormatter.currencySymbol = @"";\n    if(_abbreviationStyle == kLEAbbreviateNormal)\n        partialFormatter.maximumFractionDigits = 0;\n\n    NSString *(^partialFormat)(NSNumber*) = ^(NSNumber *num) {\n        NSString *(*superImp)(struct objc_super*,SEL,NSNumber*) = (void*)&objc_msgSendSuper;\n        return superImp(&(struct objc_super) { partialFormatter, self.superclass }, _cmd, num);\n    };\n\n    double n = [aObj doubleValue];\n    BOOL const shortFormat = _abbreviationStyle == kLEAbbreviateShort;\n\n    NSDictionary * const separators         = [self _localizedGroupingSeparators];\n    NSArray      * const separatorExponents = [separators.allKeys sortedArrayUsingSelector:@selector(compare:)];\n\n    BOOL const currencySymbolIsSuffix = [self.positiveFormat hasSuffix:@"\xc2\xa4"];\n    NSMutableString * const result = currencySymbolIsSuffix || self.numberStyle != NSNumberFormatterCurrencyStyle\n                                   ? [NSMutableString new]\n                                   : [self.currencySymbol mutableCopy];\n    NSUInteger significantDigits = 0;\n    NSNumber *lastExp = nil;\n    for(NSNumber *exp in separatorExponents.reverseObjectEnumerator) {\n        double divisor = pow(10, exp.shortValue);\n        if(divisor > n)\n            continue;\n\n        if(lastExp)\n            significantDigits += lastExp.doubleValue - exp.doubleValue;\n        lastExp = exp;\n\n        if(self.usesSignificantDigits && significantDigits >= self.maximumSignificantDigits)\n            break;\n\n        double partialNum = shortFormat\n                          ? n/divisor\n                          : floor(n/divisor);\n        NSString * const digits = [self _groupRecursively] && ![exp isEqual:@0]\n                                ? [partialFormatter stringFromNumber:@(partialNum)]\n                                : partialFormat(@(partialNum));\n        [result appendFormat:@"%@%@", digits, separators[exp]];\n\n        n = fmod(n, divisor);\n\n        if(shortFormat)\n            break; // Just use a float+first hit\n\n        // If we make it here, partialNum is integral and we can use log10 to find the number of digits\n        significantDigits += log10(partialNum) + 1;\n        partialFormatter.maximumSignificantDigits -= digits.length;\n\n    }\n    if(n > 0\n       && !shortFormat\n       && (!self.usesSignificantDigits || significantDigits < self.maximumSignificantDigits))\n    {\n        partialFormatter.maximumFractionDigits = self.maximumFractionDigits;\n        [result appendString:partialFormat(@(n))];\n    }\n    if(self.numberStyle == NSNumberFormatterCurrencyStyle && currencySymbolIsSuffix && self.currencySymbol)\n        [result appendString:self.currencySymbol];\n\n    return result.length > 0\n         ? [result stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet]\n         : [super stringForObjectValue:aObj];\n}\n\n- (BOOL)_usingKanjiNumbers\n{\n    return [self.locale.localeIdentifier rangeOfString:@"^(ja|zh)_"\n                                               options:NSRegularExpressionSearch].location != NSNotFound;\n}\n- (NSDictionary *)_localizedGroupingSeparators\n{\n    if(self._usingKanjiNumbers)\n        return @{ @2: @"\xe7\x99\xbe", @3: @"\xe5\x8d\x83", @4: @"\xe4\xb8\x87", @8: @"\xe5\x84\x84" };\n    else {\n        NSBundle * const bundle = [NSBundle bundleForClass:self.class];\n        return @{ \n            @3: [bundle localizedStringForKey:@"thousandSuffix" value:@"k " table:nil],\n            @6: [bundle localizedStringForKey:@"millionSuffix"  value:@"m " table:nil]\n        };\n    }\n}\n\n- (BOOL)_groupRecursively\n{\n    // Return _usingKanjiNumbers if you want:\n    // 12\xe5\x84\x843\xe5\x8d\x834\xe7\x99\xbe56\xe4\xb8\x877\xe5\x8d\x838\xe7\x99\xbe90\n    // Rather than:\n    // 1\xe5\x84\x842,3456\xe4\xb8\x877\xe5\x8d\x838\xe7\x99\xbe90\n    return NO;\n}\n\n- (instancetype)copyWithZone:(NSZone * const)aZone\n{\n    LENumberFormatter * const copy = [super copyWithZone:aZone];\n    copy.abbreviateLargeNumbers = _abbreviateLargeNumbers;\n    copy.abbreviationStyle      = _abbreviationStyle;\n    return copy;\n}\n@end\n\n\nint main(int argc, char *argv[]) {\n    @autoreleasepool {\n        LENumberFormatter * const f = [LENumberFormatter new];\n        f.locale = [NSLocale localeWithLocaleIdentifier:@"ja_JP"];\n//        f.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"];\n        f.numberStyle = NSNumberFormatterCurrencyStyle;\n        f.abbreviateLargeNumbers = YES;\n        f.abbreviationStyle = kLEAbbreviateNormal; // Automatic if using system locale\n        f.maximumSignificantDigits = 5;\n        f.usesSignificantDigits = YES;\n//        f.currencyCode   = @"JPY";\n//        f.currencySymbol = @"\xc2\xa5";\n\n        if([f.locale.localeIdentifier hasPrefix:@"ja"]) {\n            f.positiveFormat = @"#,##0\xc2\xa4";\n            if([f.currencyCode isEqualToString:@"JPY"])\n                // We allow ourselves this special case because *\xe6\x97\xa5\xe6\x9c\xac\xe5\x86\x86 just looks dumb\n                f.currencySymbol = @"\xe5\x86\x86";\n            else\n                f.currencySymbol = [f.locale displayNameForKey:NSLocaleCurrencyCode\n                                          value:f.currencyCode];\n        }\n\n        NSLog(@"%@", [f stringFromNumber:@1234567890]);\n        NSLog(@"%@", [f stringFromNumber:@25]);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n