Борьба с NSNumberFormatter в Swift за валюту
Я создаю бюджетное приложение, которое позволяет пользователю вводить свой бюджет, а также транзакции. Мне нужно разрешить пользователю вводить как пенсы, так и фунты из отдельных текстовых полей, и их нужно отформатировать вместе с символами валюты. На данный момент я отлично работаю, но хотел бы сделать его локализованным, поскольку в настоящее время он работает только с GBP. Я изо всех сил пытался скрыть примеры NSNumberFormatter от Objective C до Swift.
моя первая проблема заключается в том, что Мне нужно установить заполнители для полей ввода, чтобы они были специфичными для местоположения пользователей. Например. Фунты и пенсы, доллары и центы и т. д...
вторая проблема заключается в том, что значения, введенные в каждом из текстовых полей, таких как 10216 и 32, должны быть отформатированы, а символ валюты, специфичный для местоположения пользователей, должен быть добавлен. Так она станет £10,216.32 или $10,216.32 и т. д...
кроме того, мне нужно использовать результат отформатированного числа в расчете. Так как же я могу? сделать это без проблем без проблем с символа валюты?
любая помощь была бы очень признательна.
8 ответов
вот пример того, как использовать его на Swift 3. ( редактировать: работает в 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