Борьба с NSNumberFormatter в Swift за валюту
Я создаю бюджетное приложение, которое позволяет пользователю вводить свой бюджет, а также транзакции. Мне нужно разрешить пользователю вводить как пенсы, так и фунты из отдельных текстовых полей, и они должны быть отформатированы вместе с символами валюты. У меня это работает нормально на данный момент, но хотел бы сделать его локализованным, поскольку в настоящее время он работает только с GBP. Я изо всех сил пытался скрыть примеры NSNumberFormatter от Objective C до Swift.
моя первая проблема заключается в том, что Мне нужно установить заполнители для полей ввода, чтобы они были специфичны для местоположения пользователей. Например. Фунты и пенсы, доллары и центы и т. д...
вторая проблема заключается в том, что значения, введенные в каждом из текстовых полей, таких как 10216 и 32 должны быть отформатированы и символ валюты, специфичный для местоположения пользователей должны быть добавлены. Таким образом, он станет £10,216.32 или $10,216.32 и т. д...
кроме того, мне нужно использовать результат форматированного числа в вычислении. Так как же я могу сделайте это, не сталкиваясь с проблемами, не сталкиваясь с проблемами с символом валюты?
любая помощь будет высоко ценится.
8 ответов:
вот пример того, как использовать его на Swift 3. (Edit: работает в Swift 4 тоже )
let price = 123.436 as NSNumber let formatter = NumberFormatter() formatter.numberStyle = .currency // formatter.locale = NSLocale.currentLocale() // This is the default // In Swift 4, this ^ has been renamed to simply NSLocale.current formatter.string(from: price) // "3.44" formatter.locale = Locale(identifier: "es_CL") formatter.string(from: price) // 3" formatter.locale = Locale(identifier: "es_ES") formatter.string(from: price) // "123,44 €"
вот старый пример о том, как использовать его на Swift 2.
let price = 123.436 let formatter = NSNumberFormatter() formatter.numberStyle = .CurrencyStyle // formatter.locale = NSLocale.currentLocale() // This is the default formatter.stringFromNumber(price) // "3.44" formatter.locale = NSLocale(localeIdentifier: "es_CL") formatter.stringFromNumber(price) // 3" formatter.locale = NSLocale(localeIdentifier: "es_ES") formatter.stringFromNumber(price) // "123,44 €"
я реализовал решение, предоставленное @NiñoScript в качестве расширения, а также:
расширение
// Create a string with currency formatting based on the device locale // extension Float { var asLocaleCurrency:String { var formatter = NSNumberFormatter() formatter.numberStyle = .CurrencyStyle formatter.locale = NSLocale.currentLocale() return formatter.stringFromNumber(self)! } }использование:
let amount = 100.07 let amountString = amount.asLocaleCurrency print(amount.asLocaleCurrency()) // prints: "0.07"Swift 3
extension Float { var asLocaleCurrency:String { var formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = Locale.current return formatter.string(from: self)! } }
Swift 3:
Если вы ищете решение, которое дает вам:
- "5" = "$5"
- "5.0" = "$5"
- "5.00" = "$5"
- "5.5" = "$5.50"
- "5.50" = "$5.50"
- "5.55" = "$5.55"
- "5.234234" = "5.23"
пожалуйста, используйте следующие:
func cleanDollars(_ value: String?) -> String { guard value != nil else { return ".00" } let doubleValue = Double(value!) ?? 0.0 let formatter = NumberFormatter() formatter.currencyCode = "USD" formatter.currencySymbol = "$" formatter.minimumFractionDigits = (value!.contains(".00")) ? 0 : 2 formatter.maximumFractionDigits = 2 formatter.numberStyle = .currencyAccounting return formatter.string(from: NSNumber(value: doubleValue)) ?? "$\(doubleValue)" }
Xcode 9 * Swift 4
extension Locale { static let br = Locale(identifier: "pt_BR") static let us = Locale(identifier: "en_US") static let uk = Locale(identifier: "en_UK") }
extension NumberFormatter { convenience init(style: Style, locale: Locale = .current) { self.init() self.locale = locale numberStyle = style } }
extension Formatter { static let currency = NumberFormatter(style: .currency) static let currencyUS = NumberFormatter(style: .currency, locale: .us) static let currencyBR = NumberFormatter(style: .currency, locale: .br) }
extension Numeric { // for Swift 3 use FloatingPoint or Int var currency: String { return Formatter.currency.string(for: self) ?? "" } var currencyUS: String { return Formatter.currencyUS.string(for: self) ?? "" } var currencyBR: String { return Formatter.currencyBR.string(for: self) ?? "" } }
let price = 1.99 print(Formatter.currency.locale) // "en_US (current)\n" print(price.currency) // ".99\n" Formatter.currency.locale = .br print(price.currency) // "R,99\n" Formatter.currency.locale = .uk print(price.currency) // "£1.99\n" print(price.currencyBR) // "R,99\n" print(price.currencyUS) // ".99\n"
подробности
xCode 9.2, Swift 4
Решение 1
import Foundation extension String { var toLocale: Locale { return Locale(identifier: self) } } extension Numeric { func currency(numberStyle: NumberFormatter.Style = NumberFormatter.Style.currency, locale: String, groupingSeparator: String? = nil, decimalSeparator: String? = nil) -> String? { return currency(numberStyle: numberStyle, locale: locale.toLocale, groupingSeparator: groupingSeparator, decimalSeparator: decimalSeparator) } func currency(numberStyle: NumberFormatter.Style = NumberFormatter.Style.currency, locale: Locale = Locale.current, groupingSeparator: String? = nil, decimalSeparator: String? = nil) -> String? { if let num = self as? NSNumber { let formater = NumberFormatter() formater.locale = locale formater.numberStyle = numberStyle var formatedSting = formater.string(from: num) if let separator = groupingSeparator, let localeValue = locale.groupingSeparator { formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator) } if let separator = decimalSeparator, let localeValue = locale.decimalSeparator { formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator) } return formatedSting } return nil } }использование
let price = 12423.42 print(price.currency() ?? "nil") print(price.currency(numberStyle: .currencyISOCode) ?? "nil") print(price.currency(locale: "es_ES") ?? "nil") print(price.currency(locale: "es_ES", groupingSeparator: "_", decimalSeparator: ".") ?? "nil")результат
решение 2
import Foundation extension String { var toLocale: Locale { return Locale(identifier: self) } } class NumFormatter { static var shared = NumFormatter() public private(set) var formater = NumberFormatter() public private(set) var groupingSeparator: String? = nil public private(set) var decimalSeparator: String? = nil public var locale: Locale { return formater.locale } class func locale(string: String) -> NumFormatter.Type { NumFormatter.shared.formater.locale = string.toLocale return NumFormatter.self } class func number(style: NumberFormatter.Style = NumberFormatter.Style.currency) -> NumFormatter.Type { NumFormatter.shared.formater.numberStyle = style return NumFormatter.self } class func number(groupingSeparator: String?) -> NumFormatter.Type { NumFormatter.shared.groupingSeparator = groupingSeparator return NumFormatter.self } class func number(decimalSeparator: String?) -> NumFormatter.Type { NumFormatter.shared.decimalSeparator = decimalSeparator return NumFormatter.self } } extension Numeric { func currency() -> String? { if let num = self as? NSNumber { let formater = NumFormatter.shared.formater var formatedSting = formater.string(from: num) if let separator = NumFormatter.shared.groupingSeparator, let localeValue = formater.locale.groupingSeparator { formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator) } if let separator = NumFormatter.shared.decimalSeparator, let localeValue = formater.locale.decimalSeparator { formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator) } return formatedSting } return nil } }использование
let price = 12423.42 print(price.currency() ?? "nil") NumFormatter.number(style: .currencyISOCode) print(price.currency() ?? "nil") NumFormatter.locale(string: "es_ES") print(price.currency() ?? "nil") NumFormatter.number(groupingSeparator: "_").number(decimalSeparator: ".") print(price.currency() ?? "nil")
Swift 4
formatter.locale = Locale.currentЕсли вы хотите изменить язык вы можете сделать это
formatter.locale = Locale.init(identifier: "id-ID")// это локаль для Индонезии локаль. если вы хотите использовать в соответствии с областью мобильного телефона, используйте его в соответствии с языковым стандартом верхнего упоминания.ток
//MARK:- Complete code let formatter = NumberFormatter() formatter.numberStyle = .currency if let formattedTipAmount = formatter.string(from: Int(newString)! as NSNumber) { yourtextfield.text = formattedTipAmount }
добавить эту функцию
func addSeparateMarkForNumber(int: Int) -> String { var string = "" let formatter = NumberFormatter() formatter.locale = Locale.current formatter.numberStyle = .decimal if let formattedTipAmount = formatter.string(from: int as NSNumber) { string = formattedTipAmount } return string }использование:
let giaTri = value as! Int myGuessTotalCorrect = addSeparateMarkForNumber(int: giaTri)
extension Float { var convertAsLocaleCurrency :String { var formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = Locale.current return formatter.string(from: self as NSNumber)! } }это работает для swift 3.1 xcode 8.2.1

Comments