iOS: Remove thousand separator in NSDecimalNumber for edit

删除回忆录丶 提交于 2020-01-14 05:10:27

问题


I have decimal numbers stored in my database as decimal. And I display them according to the user's locale:

- (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;
}

And I display these strings in textfields, that are editable. So if a user starts to edit the field, I want to remove the thousand separator. Otherwise (in my country) I enter 1'000.55 and it then doesn't recognize the "'" and saves just a 1. Here is my function to parse the textfields and in the view controllers this exact return value will be saved to the database:

+ (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];
    }

However I don't get it to work...actually it would be best if numbers with"'" and without would be saved correctly but I don't get it to work :/

EDIT (my solution): Got it working like this:

- (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

interprets now every string correctly. 1'000 and 1000 and 1000.00 are all 1000 now :-)


回答1:


The simplest and most clean solution I believe is this:

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



回答2:


I see a couple of problems with your code, and am also not clear what it is you want to do.

The first problem is that in your method getLocalizedCurrencyStringWithDigits, you are calling stringFromNumber and passing in "self". That does not make sense, unless you are creating a custom subclass of NSNumber, which I doubt you are doing.

Next problem is that you are using the NSDecimalNumber class, which I suspect is not what you think it is. It is a special subclass of NSNumber that is designed for doing base 10 math without the rounding errors you get doing math on fractional numbers using binary arithmetic. NSDecimalNumber is a very specialized class, and unless you know exactly why you are using it, it is not what you need. Just use a regular NSNumber instead.

Then the next problem. You say you are trying to "remove the thousands separator." What thousands separator? If you convert a number value to a string then it should be in the correct format for the user's locale. Also, why are you using NSNumberFormatterDecimalStyle If what you want to display is currency amounts? Shouldn't you be using NSNumberFormatterCurrencyStyle instead?




回答3:


Set usesGroupingSeparator to NO (or false in Swift) on your NSNumberFormatter instance.

It maintains the decimal separator while removing the rest of grouping separators.




回答4:


From this answer, remove all characters that are not a number or a decimal and you should get a stripped string with only a valid number when converted using NSNumberFormatter or floatValue

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)];
  }
}

Or you could use a regular expression:

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

I can't swear by the regular expression syntax used here as I stole if from here. I don't have much experience there.



来源:https://stackoverflow.com/questions/21390264/ios-remove-thousand-separator-in-nsdecimalnumber-for-edit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!