Estou criando um aplicativo de orçamento que permite ao usuário inserir seu orçamento, bem como transações. Preciso permitir que o usuário insira pence e libras em campos de texto separados e eles precisam ser formatados junto com os símbolos de moeda. Eu estou funcionando bem no momento, mas gostaria de torná-lo localizado, pois atualmente ele só funciona com GBP. Tenho lutado para converter exemplos NSNumberFormatter do Objective C para o Swift.
Meu primeiro problema é o fato de que preciso definir os espaços reservados para os campos de entrada para serem específicos ao local dos usuários. Por exemplo. Libras e Pence, Dólares e Cêntimos etc ...
O segundo problema é que os valores inseridos em cada um dos campos de texto, como 10216 e 32, precisam ser formatados e o símbolo de moeda específico para a localização do usuário precisa ser adicionado. Portanto, seria £ 10.216,32 ou $ 10.216,32 etc ...
Além disso, preciso usar o resultado do número formatado em um cálculo. Então, como posso fazer isso sem ter problemas sem ter problemas com o símbolo da moeda?
Qualquer ajuda seria muito apreciada.
fonte
Respostas:
Aqui está um exemplo de como usá-lo no Swift 3. ( Editar : Funciona no Swift 4 também)
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 €"
Aqui está o exemplo antigo de como usá-lo no 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 €"
fonte
string(for: price)
vez destring(from: price)
Swift 3:
Se você está procurando uma solução que ofereça:
Use o seguinte:
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)" }
fonte
func string(for obj: Any?) -> String?
vez destring(from:)
Eu implementei a solução fornecida por @NiñoScript como uma extensão também:
Extensão
// 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)! } }
Uso:
let amount = 100.07 let amountString = amount.asLocaleCurrency print(amount.asLocaleCurrency()) // prints: "$100.07"
Swift 3
extension Float { var asLocaleCurrency:String { var formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = Locale.current return formatter.string(from: self)! } }
fonte
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"
fonte
Detalhes
Solução
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 } }
Uso
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")
Resultados
$12,423.42 USD12,423.42 12.423,42 € 12 423,42 EUR 12_423.42 US dollars 12 423,42 Euro
fonte
Atualizado para Swift 4 a partir da resposta de @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 ?? "" } }
Nota: nenhum desempacotamento forçado, o desempacotamento forçado é mau.
fonte
Swift 4 TextField implementado
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 }
fonte
extension Float { var convertAsLocaleCurrency :String { var formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = Locale.current return formatter.string(from: self as NSNumber)! } }
Isso funciona para swift 3.1 xcode 8.2.1
fonte
Swift 4
formatter.locale = Locale.current
se você quiser mudar de local, você pode fazer assim
formatter.locale = Locale.init(identifier: "id-ID")
// Este é o local para o local da Indonésia. se você quiser usar de acordo com a área do telefone móvel, use-o de acordo com a menção superior Locale.current
//MARK:- Complete code let formatter = NumberFormatter() formatter.numberStyle = .currency if let formattedTipAmount = formatter.string(from: Int(newString)! as NSNumber) { yourtextfield.text = formattedTipAmount }
fonte
adicione esta função
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 }
usando:
let giaTri = value as! Int myGuessTotalCorrect = addSeparateMarkForNumber(int: giaTri)
fonte