Tworzę aplikację budżetową, która pozwala użytkownikowi wprowadzić budżet, a także transakcje. Muszę pozwolić użytkownikowi na wprowadzanie zarówno pensów, jak i funtów z oddzielnych pól tekstowych i muszą być one sformatowane razem z symbolami walut. W tej chwili to działa dobrze, ale chciałbym, aby było zlokalizowane, ponieważ obecnie działa tylko z GBP. Próbowałem ukryć przykłady NSNumberFormatter od Objective C do Swift.
Moim pierwszym problemem jest to, że muszę ustawić symbole zastępcze dla pól wejściowych, aby były specyficzne dla lokalizacji użytkowników. Na przykład. Funty i pensy, dolary i centy itp.
Drugą kwestią jest to, że wartości wprowadzane w każdym z pól tekstowych, takich jak 10216 i 32, muszą zostać sformatowane i należy dodać symbol waluty właściwy dla lokalizacji użytkownika. Stałby się więc 10216,32 GBP lub 10216,32 USD itd.
Muszę również użyć wyniku sformatowanej liczby w obliczeniach. Jak więc mogę to zrobić bez napotykania problemów bez napotykania problemów z symbolem waluty?
Każda pomoc byłaby bardzo mile widziana.
źródło
Odpowiedzi:
Oto przykład, jak go używać w Swift 3. ( Edycja : działa również w 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) // "$123.44" formatter.locale = Locale(identifier: "es_CL") formatter.string(from: price) // $123" formatter.locale = Locale(identifier: "es_ES") formatter.string(from: price) // "123,44 €"
Oto stary przykład, jak go używać w Swift 2.
let price = 123.436 let formatter = NSNumberFormatter() formatter.numberStyle = .CurrencyStyle // formatter.locale = NSLocale.currentLocale() // This is the default formatter.stringFromNumber(price) // "$123.44" formatter.locale = NSLocale(localeIdentifier: "es_CL") formatter.stringFromNumber(price) // $123" formatter.locale = NSLocale(localeIdentifier: "es_ES") formatter.stringFromNumber(price) // "123,44 €"
źródło
string(for: price)
zamiaststring(from: price)
Swift 3:
Jeśli szukasz rozwiązania, które zapewni Ci:
Użyj następujących:
func cleanDollars(_ value: String?) -> String { guard value != nil else { return "$0.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)" }
źródło
func string(for obj: Any?) -> String?
zamiaststring(from:)
Wdrożyłem rozwiązanie dostarczone przez @ NiñoScript również jako rozszerzenie:
Rozbudowa
// 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)! } }
Stosowanie:
let amount = 100.07 let amountString = amount.asLocaleCurrency print(amount.asLocaleCurrency()) // prints: "$100.07"
Szybki 3
extension Float { var asLocaleCurrency:String { var formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = Locale.current return formatter.string(from: self)! } }
źródło
Xcode 11 • Swift 5.1
extension Locale { static let br = Locale(identifier: "pt_BR") static let us = Locale(identifier: "en_US") static let uk = Locale(identifier: "en_GB") // ISO Locale }
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 { var currency: String { Formatter.currency.string(for: self) ?? "" } var currencyUS: String { Formatter.currencyUS.string(for: self) ?? "" } var currencyBR: String { Formatter.currencyBR.string(for: self) ?? "" } }
let price = 1.99 print(Formatter.currency.locale) // "en_US (current)\n" print(price.currency) // "$1.99\n" Formatter.currency.locale = .br print(price.currency) // "R$1,99\n" Formatter.currency.locale = .uk print(price.currency) // "£1.99\n" print(price.currencyBR) // "R$1,99\n" print(price.currencyUS) // "$1.99\n"
źródło
Detale
Rozwiązanie
import Foundation class CurrencyFormatter { static var outputFormatter = CurrencyFormatter.create() class func create(locale: Locale = Locale.current, groupingSeparator: String? = nil, decimalSeparator: String? = nil, style: NumberFormatter.Style = NumberFormatter.Style.currency) -> NumberFormatter { let outputFormatter = NumberFormatter() outputFormatter.locale = locale outputFormatter.decimalSeparator = decimalSeparator ?? locale.decimalSeparator outputFormatter.groupingSeparator = groupingSeparator ?? locale.groupingSeparator outputFormatter.numberStyle = style return outputFormatter } } extension Numeric { func toCurrency(formatter: NumberFormatter = CurrencyFormatter.outputFormatter) -> String? { guard let num = self as? NSNumber else { return nil } var formatedSting = formatter.string(from: num) guard let locale = formatter.locale else { return formatedSting } if let separator = formatter.groupingSeparator, let localeValue = locale.groupingSeparator { formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator) } if let separator = formatter.decimalSeparator, let localeValue = locale.decimalSeparator { formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator) } return formatedSting } }
Stosowanie
let price = 12423.42 print(price.toCurrency() ?? "") CurrencyFormatter.outputFormatter = CurrencyFormatter.create(style: .currencyISOCode) print(price.toCurrency() ?? "nil") CurrencyFormatter.outputFormatter = CurrencyFormatter.create(locale: Locale(identifier: "es_ES")) print(price.toCurrency() ?? "nil") CurrencyFormatter.outputFormatter = CurrencyFormatter.create(locale: Locale(identifier: "de_DE"), groupingSeparator: " ", style: .currencyISOCode) print(price.toCurrency() ?? "nil") CurrencyFormatter.outputFormatter = CurrencyFormatter.create(groupingSeparator: "_", decimalSeparator: ".", style: .currencyPlural) print(price.toCurrency() ?? "nil") let formatter = CurrencyFormatter.create(locale: Locale(identifier: "de_DE"), groupingSeparator: " ", decimalSeparator: ",", style: .currencyPlural) print(price.toCurrency(formatter: formatter) ?? "nil")
Wyniki
$12,423.42 USD12,423.42 12.423,42 € 12 423,42 EUR 12_423.42 US dollars 12 423,42 Euro
źródło
Zaktualizowano dla Swift 4 z odpowiedzi @Michael Voccola:
extension Double { var asLocaleCurrency: String { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = Locale.current let formattedString = formatter.string(from: self as NSNumber) return formattedString ?? "" } }
Uwaga: brak rozpinania na siłę, rozpinanie na siłę są złe.
źródło
Wdrożono Swift 4 TextField
var value = 0 currencyTextField.delegate = self func numberFormatting(money: Int) -> String { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = .current return formatter.string(from: money as NSNumber)! } currencyTextField.text = formatter.string(from: 50 as NSNumber)! func textFieldDidEndEditing(_ textField: UITextField) { value = textField.text textField.text = numberFormatting(money: Int(textField.text!) ?? 0 as! Int) } func textFieldDidBeginEditing(_ textField: UITextField) { textField.text = value }
źródło
extension Float { var convertAsLocaleCurrency :String { var formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = Locale.current return formatter.string(from: self as NSNumber)! } }
To działa dla Swift 3.1 xcode 8.2.1
źródło
Szybki 4
formatter.locale = Locale.current
jeśli chcesz zmienić lokalizację, możesz to zrobić w ten sposób
formatter.locale = Locale.init(identifier: "id-ID")
// To jest ustawienie regionalne dla Indonezji. jeśli chcesz korzystać z obszaru telefonu komórkowego, użyj go zgodnie z powyższą wzmianką Locale.current
//MARK:- Complete code let formatter = NumberFormatter() formatter.numberStyle = .currency if let formattedTipAmount = formatter.string(from: Int(newString)! as NSNumber) { yourtextfield.text = formattedTipAmount }
źródło
dodaj tę funkcję
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 }
za pomocą:
let giaTri = value as! Int myGuessTotalCorrect = addSeparateMarkForNumber(int: giaTri)
źródło