Преобразовать строку в NSDecimalNumber

Я пытаюсь преобразовать String в NSDecimalNumber, здесь это мой код:

class func stringToDecimal (dataToDecimal: String) -> NSDecimalNumber {

    let dataToDecimal = dataToDecimal.stringByReplacingOccurrencesOfString(",", withString: ".")
    print(dataToDecimal)
    let  decimalReturn = NSDecimalNumber(string: dataToDecimal)
    print(decimalReturn)

    if decimalReturn == NSDecimalNumber.notANumber(){
        return 0.00
    }
    return decimalReturn
}

Сначала я подумал, что, может быть, это неправильно, но даже с. он не работает. Первая печать (до преобразования) показывает, например, 80,00, но печать (decimalReturn) показывает только 80

строка if - это просто проверить, не является ли результат не числом.

Ответ 1

Используйте NSNumberFormatter для анализа вашего ввода. Установите для свойства generatesDecimalNumbers значение true:

let formatter = NumberFormatter()
formatter.generatesDecimalNumbers = true

Вот как вы его используете, если вы хотите вернуть 0, когда строка не может быть проанализирована:

func decimal(with string: String) -> NSDecimalNumber {
    return formatter.number(from: string) as? NSDecimalNumber ?? 0
}

decimal(with: "80.00")

// Result: 80 as an NSDecimalNumber

По умолчанию форматер будет искать настройку локали устройства, чтобы определить десятичный маркер. Вы должны оставить это таким образом. Например, я буду принуждать его к французскому языку:

// DON'T DO THIS. Just an example of behavior in a French locale.
formatter.locale = Locale(identifier: "fr-FR")

decimal(with: "80,00")
// Result: 80

decimal(with: "80.00")
// Result: 0

Если вы действительно хотите использовать запятую в качестве десятичной метки, вы можете установить свойство decimalSeparator:

formatter.decimalSeparator = ","

Ответ 2

Нет ничего плохого в том, как вы создаете NSDecimalNumber из String. Однако вам может не понадобиться беспокоиться о замене запятой на период, если это так, как ваши локальные форматы.

Причина, по которой он печатает 80 вместо 80,00 или 80,00, заключается в том, что print просто использует свойство description для числа. Если вы хотите настроить форматирование, вы должны настроить свой собственный NSNumberFormatter.

let number = NSDecimalNumber(string: "80.00")
print(number) // 80
let formatter = NSNumberFormatter()
formatter.minimumFractionDigits = 2
let string = formatter.stringFromNumber(number)
print(string) // 80.0

Ответ 3

Когда сервер вызывает какую-то определенную локаль, используйте ее вместо Locale.current. чтобы вы не хотели поломки в зависимости от настроек пользователя

extension String {
    var decimalFromServerString: NSDecimalNumber? {
        let parsed = NSDecimalNumber(string: self, locale: ru_ru_posix)
        if parsed == .notANumber {
            return nil
        }
        return parsed
    }
}

PS. если по какой-то причине вы жестко привязываете язык к en_US POSIX, то строка "..." выходит как 0. Пройдите рисунок: - [