Convert NSSting to NSDecimalNumber based on locale

262 views Asked by At

I want to convert a number which is input as NSString to NSDecimalNumber based on NSLocale.

for example

InputString => 110.50
Current Locale => en_FI
Expected output => 110.50
Actual output => 110

InputString => 110.50
Current Locale => en_US
Expected output => 110.50
Actual output => 110.50



InputString => 110,50
Current Locale => en_US
Expected output => 110.50
Actual output => 110


InputString => 110.50
Current Locale => en_US
Expected output => 110.50
Actual output => 110.50

I am using the following code to achieve this but its not working.

NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:self.amountTextField.text locale:[NSLocale currentLocale]];

As mentioned above in 1st and 3rd i am not the desired output. Any idea what i am doing wrong here.

2

There are 2 answers

7
Tim Bernikovich On

I propose you to specify NumberFormatters decimalSeparator yourself and in input string replace , and . with same character you used in decimalSeparator.

import Foundation

let formatter = NumberFormatter()
formatter.numberStyle = .decimal

func cleanNumberString(with string: String) -> String {
    let knownDecimalSeparators = [",", "."]
    let localSeparator = formatter.decimalSeparator ?? "."
    var cleanString = string;
    for separator in knownDecimalSeparators {
        cleanString = cleanString.replacingOccurrences(of: separator, with: localSeparator)
    }
    return cleanString
}

func number(with string: String) -> Double {
    let cleanString = cleanNumberString(with: string)
    let number = formatter.number(from: cleanString)
    return number?.doubleValue ?? 0
}

let string1 = "14,4"
let string2 = "14.4"

let cleanString1 = cleanNumberString(with: string1)
let cleanString2 = cleanNumberString(with: string2)

let number1 = number(with: string1)
let number2 = number(with: string2)

Same in Objective-C

@interface CleanNumberFormatter ()

@property (nonatomic) NSNumberFormatter *formatter;

@end

@implementation CleanNumberFormatter

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.formatter = [NSNumberFormatter new];
        self.formatter.numberStyle = NSNumberFormatterDecimalStyle;
    }
    return self;
}

- (NSString *)cleanNumberStringWithString:(NSString *)string
{
    NSArray *knownDecimalSeparators = @[@",", @"."];
    NSString *localSeparator = self.formatter.decimalSeparator ?: @",";
    NSString *cleanString = [string copy];
    for (NSString *separator in knownDecimalSeparators) {
        cleanString = [cleanString stringByReplacingOccurrencesOfString:separator withString:localSeparator];
    }
    return cleanString;
}

- (double)numberWithString:(NSString *)string
{
    NSString *cleanString = [self cleanNumberStringWithString:string];
    double number = [self.formatter numberFromString:cleanString].doubleValue;
    return number;
}

- (void)foo
{
    NSString *string1 = @"14.4";
    NSString *string2 = @"14,4";

    NSString *cleanString1 = [self cleanNumberStringWithString:string1];
    NSString *cleanString2 = [self cleanNumberStringWithString:string2];

    double number1 = [self numberWithString:string1];
    double number2 = [self numberWithString:string2];
}

@end
2
Julius On

The only numbers that do not have the expected output have a comma instead of a period and a period instead of a comma in the input. Try replacing that and see if it works as some locals use different decimal separators.