Invoer voor valuta opmaken met NSNumberFormatter in Swift

Ik ben een budget-app aan het maken waarmee de gebruiker zijn budget en transacties kan invoeren. Ik moet de gebruiker toestaan ​​om zowel pence als ponden uit afzonderlijke tekstvelden in te voeren en ze moeten samen met valutasymbolen worden opgemaakt. Ik heb dit momenteel goed werkend, maar zou het graag gelokaliseerd willen maken omdat het momenteel alleen werkt met GBP. Ik heb moeite met het converteren van NSNumberFormatter-voorbeelden van Objective-C naar Swift.

Mijn eerste probleem is het feit dat ik de tijdelijke aanduidingen voor de invoervelden moet instellen om specifiek te zijn voor de locatie van de gebruiker. bijv. Ponden en pence, dollars en centen enz…

Het tweede probleem is dat de waarden die worden ingevoerd in elk van de tekstvelden, zoals 10216 en 32, moeten worden opgemaakt en dat het valutasymbool dat specifiek is voor de locatie van de gebruiker moet worden toegevoegd. Dus het zou £10.216.32 of $10.216.32 enz. worden…

Ook moet ik het resultaat van het opgemaakte getal in een berekening gebruiken. Dus hoe kan ik dit doen zonder problemen te krijgen zonder problemen met het valutasymbool?


Antwoord 1, autoriteit 100%

Hier is een voorbeeld van hoe u het op Swift 3 kunt gebruiken.
( Bewerken: werkt ook in Swift 5 )

let price = 123.436 as NSNumber
let formatter = NumberFormatter()
formatter.numberStyle = .currency
// formatter.locale = NSLocale.currentLocale() // This is the default
// In Swift 4, this ^ was 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 €"

Hier is het oude voorbeeld van hoe het te gebruiken op 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 €"

Antwoord 2, autoriteit 13%

Swift 3:

Als u op zoek bent naar een oplossing die u het volgende biedt:

  • “5” = “$5”
  • “5.0” = “$5”
  • “5,00” = “$5”
  • “5.5” = “$5.50”
  • “5.50” = “$5.50”
  • “5.55” = “$5.55”
  • “5.234234” = “5.23”

Gebruik het volgende:

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)"
}

Antwoord 3, autoriteit 9%

Ik heb de oplossing van @NiñoScript ook als extensie geïmplementeerd:

Extensie

// 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)!
    }
}

Gebruik:

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)!
    }
}

Antwoord 4, autoriteit 8%

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"

Antwoord 5, autoriteit 3%

Details

  • Xcode 10.2.1 (10E1001), Swift 5

Oplossing

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
    }
}

Gebruik

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")

Resultaten

$12,423.42
USD12,423.42
12.423,42 €
12 423,42 EUR
12_423.42 US dollars
12 423,42 Euro

Antwoord 6

Bijgewerkt voor Swift 4 van @Michael Voccola’s antwoord:

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 ?? ""
    }
}

Opmerking: geforceerd uitpakken is niet nodig, geforceerd uitpakken is slecht.


Antwoord 7

Swift 4 TextField geïmplementeerd

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
}

Antwoord 8

extension Float {
    var convertAsLocaleCurrency :String {
        var formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = Locale.current
        return formatter.string(from: self as NSNumber)!
    }
}

Dit werkt voor swift 3.1 xcode 8.2.1


Antwoord 9

Swift 4

formatter.locale = Locale.current

als u de landinstelling wilt wijzigen, kunt u dat als volgt doen

formatter.locale = Locale.init(identifier: "id-ID") 

// Dit is de landinstelling voor de Indonesische landinstelling. als je het wilt gebruiken volgens het gebied van de mobiele telefoon, gebruik het dan volgens de bovenste vermelding Locale.current

//MARK:- Complete code
let formatter = NumberFormatter()
formatter.numberStyle = .currency
    if let formattedTipAmount = formatter.string(from: Int(newString)! as 
NSNumber) { 
       yourtextfield.text = formattedTipAmount
}

Antwoord 10

voeg deze functie toe

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
}

gebruik:

let giaTri = value as! Int
myGuessTotalCorrect = addSeparateMarkForNumber(int: giaTri)

Other episodes