【问题标题】:iOS: Remove thousand separator in NSDecimalNumber for editiOS:删除 NSDecimalNumber 中的千位分隔符进行编辑
【发布时间】:2014-01-27 19:49:55
【问题描述】:

我将十进制数字作为十进制存储在我的数据库中。我根据用户的语言环境显示它们:

- (NSString *) getLocalizedCurrencyStringWithDigits
{
    NSNumberFormatter *numberFormatter =[[NSNumberFormatter alloc] init];
    [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [numberFormatter setLocale:[NSLocale currentLocale]];
    [numberFormatter setMinimumFractionDigits:2];
    [numberFormatter setMaximumFractionDigits:2];

    NSString *numberString = [numberFormatter stringFromNumber:self];

    return numberString;
}

我将这些字符串显示在可编辑的文本字段中。因此,如果用户开始编辑该字段,我想删除千位分隔符。否则(在我的国家)我输入 1'000.55,然后它无法识别“'”并只保存一个 1。这是我解析文本字段的函数,在视图控制器中,这个确切的返回值将保存到数据库:

+ (NSDecimalNumber *) getUnLocalizedDecimalNumberWithString:(NSString *)currencyString
{
    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [numberFormatter setLocale:[NSLocale currentLocale]];
    [numberFormatter setMinimumFractionDigits:2];
    [numberFormatter setMaximumFractionDigits:2];

    BOOL isDecimal = [numberFormatter numberFromString:currencyString] != nil;
    if(isDecimal){
        return [NSDecimalNumber decimalNumberWithString:currencyString locale:[NSLocale currentLocale]];
    } else {
        return [NSDecimalNumber zero];
    }

但是我不能让它工作...实际上最好是正确保存带有“'”和不带的数字,但我不能让它工作:/

编辑(我的解决方案): 让它像这样工作:

- (NSString *) getLocalizedCurrencyStringWithDigits:(int)digits
{
    NSNumberFormatter *numberFormatter =[[NSNumberFormatter alloc] init];
    [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [numberFormatter setLocale:[NSLocale currentLocale]];
    [numberFormatter setMinimumFractionDigits:digits];
    [numberFormatter setMaximumFractionDigits:digits];

    NSString *numberString = [numberFormatter stringFromNumber:self];

    return numberString;
}

+ (NSDecimalNumber *) getUnLocalizedDecimalNumberWithString:(NSString *)currencyString
{
    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
    [numberFormatter setLocale:[NSLocale currentLocale]];
    [numberFormatter setMinimumFractionDigits:2];
    [numberFormatter setMaximumFractionDigits:2];

    NSNumber *formatedCurrency = [numberFormatter numberFromString:currencyString];

    BOOL isDecimal = formatedCurrency != nil;
    if(isDecimal){
        return [NSDecimalNumber decimalNumberWithDecimal:[formatedCurrency decimalValue]];
    } else {
        return [NSDecimalNumber zero];
    }
}

+(NSDecimalNumber *) getUnLocalizedDecimalNumberWithString:(NSString *)currencyString

现在可以正确解释每个字符串。 1'000 和 1000 和 1000.00 现在都是 1000 :-)

【问题讨论】:

  • 如果您解决了自己的问题,您应该发布解决方案作为答案,然后接受(一旦系统允许)。
  • 是的,首先我想这样做,但后来我想先看看我的解决方案是否可以这样。我的意思是,如果我首先将字符串转换为 NSNumber,然后再转换为 NSDecimalNumber,从而丢失任何精度。或者,如果我创建了太多对象......我仍在学习每一行代码:)

标签: ios objective-c localization nsnumberformatter


【解决方案1】:

我认为最简单、最干净的解决方案是:

NSLocale *locale = [NSLocale currentLocale];
NSString *thousandSeparator = [locale objectForKey:NSLocaleGroupingSeparator];
NSString *result = [decimalStringWithThousandSeperator stringByReplacingOccurrencesOfString:thousandSeparator withString:@""];

【讨论】:

    【解决方案2】:

    在您的 NSNumberFormatter 实例上将 usesGroupingSeparator 设置为 NO(或 Swift 中的 false)。

    它保留小数分隔符,同时删除其余的分组分隔符。

    【讨论】:

      【解决方案3】:

      我发现您的代码存在一些问题,也不清楚您想要做什么。

      第一个问题是在您的方法 getLocalizedCurrencyStringWithDigits 中,您正在调用 stringFromNumber 并传入“self”。这没有任何意义,除非您正在创建 NSNumber 的自定义子类,我怀疑您正在这样做。

      下一个问题是您使用的是 NSDecimalNumber 类,我怀疑它不是您想的那样。它是 NSNumber 的一个特殊子类,旨在进行以 10 为底的数学运算,而不会出现使用二进制算术对小数进行数学运算时遇到的舍入错误。 NSDecimalNumber 是一个非常专业的类,除非您确切知道为什么要使用它,否则它不是您所需要的。只需使用常规的 NSNumber。

      然后下一个问题。您说您正在尝试“删除千位分隔符”。什么千位分隔符?如果将数字值转换为字符串,那么它的格式应该适合用户的区域设置。另外,如果您要显示的是货币金额,为什么要使用 NSNumberFormatterDecimalStyle?你不应该改用 NSNumberFormatterCurrencyStyle 吗?

      【讨论】:

      • 1.是的,这就是我正在做的,它是 NSDecimalNumber 2 上的一个类别。我正在使用 NSDecimalNumber,因为我正在处理货币并需要精确值 3。我使用的是小数样式,因为我不需要像 $ 这样的任何货币符号管他呢。在我的字符串中,我从我的方法中得到了一个千位分隔符,并且解析无法识别它......
      • NSNumber 是一个类簇。对属于类簇一部分的对象进行子类化具有特殊要求。您是否知道对类集群的成员进行子类化所需的特殊步骤?
      • 你需要让你的读者更全面地了解你在做什么。我们需要知道您发布的代码是 NSDecimalNumber 的自定义子类的一部分。您可能应该概述一下您对这个特殊子类的目标是什么,以及您要添加的方法,以及您如何处理您正在对类集群的成员进行子类化这一事实。
      • 抱歉,我还是 iOS 新手:-/ 不,我不知道子类化有特殊要求?好吧,我实际上并不是只创建一个类别的子类,还是一样?我只想将我在核心数据数据库中存储为十进制的数字转换为本地化字符串以供显示。并且用户可以更改这些值。所以我的类别(类方法)也应该解析这个更改的值并从这个(本地化)字符串中生成一个 NSDecimalNumber 以将其存储回 coredata
      • @MichiZH,没有一个类别与子类不同,只要您不尝试覆盖已在类中定义的方法,就不会对类集群造成与您相同的问题使用子类化。
      【解决方案4】:

      From this answer,删除所有不是数字或小数的字符,当使用NSNumberFormatterfloatValue 转换时,您应该得到一个只有有效数字的剥离字符串

      NSScanner *scanner = [NSScanner scannerWithString:originalString];
      NSCharacterSet *numbers = [NSCharacterSet 
              characterSetWithCharactersInString:@".0123456789"];
      
      while ([scanner isAtEnd] == NO) {
        NSString *buffer;
        if ([scanner scanCharactersFromSet:currencyString intoString:&buffer]) {
          [strippedString appendString:buffer];
      
        } else {
          [scanner setScanLocation:([scanner scanLocation] + 1)];
        }
      }
      

      或者你可以使用正则表达式:

      NSString * strippedNumber = [currencyString stringByReplacingOccurrencesOfRegex:@"^([0-9]+)?(\\.([0-9]{1,2})?)?$" withString:@""];
      

      我不能对这里使用的正则表达式语法发誓I stole if from here。我在那里没有太多经验。

      【讨论】:

      • 这很危险,因为它没有考虑用户的语言环境。例如德语字符串“1.000,80”将变成“1.0008”丢失正确的小数点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-06
      相关资源
      最近更新 更多