我正在创建一个预算应用,允许用户输入预算和交易。我需要允许用户从单独的文本字段输入便士和磅数,并且需要将它们与货币符号一起格式化。我现在工作得很好,但是想把它本地化,因为目前它只适用于GBP。我一直在努力将NSNumberFormatter的例子从Objective C转换为Swift。
我的第一个问题是我需要将输入字段的占位符设置为特定于用户位置。例如。英镑和便士,美元和美分等......
第二个问题是需要格式化在每个文本字段(例如10216和32)中输入的值,并且需要添加特定于用户位置的货币符号。所以它会变成10,216.32英镑或10,216.32美元等......
另外,我需要在计算中使用格式化数字的结果。那么如何在不遇到货币符号问题的情况下解决问题呢?
非常感谢任何帮助。
答案 0 :(得分:186)
以下是有关如何在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) // "$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 €"
这是关于如何在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 €"
答案 1 :(得分:20)
斯威夫特3:
如果您正在寻找能够为您提供的解决方案:
请使用以下内容:
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)"
}
答案 2 :(得分:19)
我已经实现了@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: "$100.07"
Swift 3
extension Float {
var asLocaleCurrency:String {
var formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = Locale.current
return formatter.string(from: self)!
}
}
答案 3 :(得分:13)
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) // "$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"
答案 4 :(得分:5)
import Foundation
class CurrencyFormatter {
static var shared = CurrencyFormatter()
private(set) lazy var outputFormatter = NumberFormatter()
class func number(localeString: String? = nil,
groupingSeparator: String? = nil,
decimalSeparator: String? = nil,
style: NumberFormatter.Style = NumberFormatter.Style.currency) -> CurrencyFormatter.Type {
var locale = Locale.current
if let localeString = localeString { locale = Locale(identifier: localeString) }
shared.outputFormatter.locale = locale
shared.outputFormatter.decimalSeparator = decimalSeparator ?? locale.decimalSeparator
shared.outputFormatter.groupingSeparator = groupingSeparator ?? locale.groupingSeparator
shared.outputFormatter.numberStyle = style
return self
}
}
extension Numeric {
func toCurrency(formatter currencyFormatter: CurrencyFormatter = CurrencyFormatter.shared) -> String? {
guard let num = self as? NSNumber else { return nil }
let outputFormatter = currencyFormatter.outputFormatter
var formatedSting = outputFormatter.string(from: num)
guard let locale = outputFormatter.locale else { return formatedSting }
if let separator = outputFormatter.groupingSeparator, let localeValue = locale.groupingSeparator {
formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator)
}
if let separator = outputFormatter.decimalSeparator, let localeValue = locale.decimalSeparator {
formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator)
}
return formatedSting
}
}
let price = 12423.42
print(price.toCurrency() ?? "nil")
CurrencyFormatter.number(style: .currencyISOCode)
print(price.toCurrency() ?? "nil")
CurrencyFormatter.number(localeString: "es_ES")
print(price.toCurrency() ?? "nil")
CurrencyFormatter.number(localeString: "de_DE", groupingSeparator: " ", style: .currencyISOCode)
print(price.toCurrency() ?? "nil")
CurrencyFormatter.number(groupingSeparator: "_", decimalSeparator: ".", style: .currencyPlural)
print(price.toCurrency() ?? "nil")
12423
USD12,423.42
12.423,42 €
12 423,42 EUR
12_423.42 US dollars
答案 5 :(得分:2)
已从@Michael Voccola的答案更新为Swift 4:
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 ?? ""
}
}
注意:没有强制拆开,强制拆开是邪恶的。
答案 6 :(得分:1)
已实现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
}
答案 7 :(得分:0)
Swift 4
formatter.locale = Locale.current
如果你想改变语言环境,你可以这样做
formatter.locale = Locale.init(identifier: "id-ID")
//这是印度尼西亚语区域设置的区域设置。如果您想按照手机区域使用,请按照上面提到的Locale.current
使用它//MARK:- Complete code
let formatter = NumberFormatter()
formatter.numberStyle = .currency
if let formattedTipAmount = formatter.string(from: Int(newString)! as
NSNumber) {
yourtextfield.text = formattedTipAmount
}
答案 8 :(得分:0)
添加此功能
'Declare objects
Dim oSDO As SageDataObject230.SDOEngine
Dim oWS As SageDataObject230.WorkSpace
Dim oSOPRecord As SageDataObject230.SopRecord
Dim oSOPItem_Read As SageDataObject230.SopItem
Dim oSOPItem_Write As SageDataObject230.SopItem
Dim oSOPPost As SageDataObject230.SopPost
Dim oStockRecord As SageDataObject230.StockRecord
'Declare Variables
Dim szDataPath As String
'Create SDO Engine Object
oSDO = New SageDataObject230.SDOEngine
' Select company. The SelectCompany method takes the program install
' folder as a parameter
szDataPath = oSDO.SelectCompany("C:\Documents and Settings\All Users\Application Data\Sage\Accounts\2017\")
'Create Workspace
oWS = oSDO.Workspaces.Add("Example")
'Try to connect
If oWS.Connect(szDataPath, "manager", "", "Example") Then
'Create objects
oSOPRecord = oWS.CreateObject("SOPRecord")
oSOPPost = oWS.CreateObject("SOPPost")
oSOPItem_Read = oWS.CreateObject("SOPItem")
oStockRecord = oWS.CreateObject("StockRecord")
'Read an existing Sales Order
oSOPRecord.MoveLast()
'Populate the order header, copying fields from oSOPRecord to oSOPPost
oSOPPost.Header("INVOICE_NUMBER").Value = oSOPRecord.Fields.Item("INVOICE_NUMBER").Value
oSOPPost.Header("ACCOUNT_REF").Value = CStr(oSOPRecord.Fields.Item("ACCOUNT_REF").Value)
oSOPPost.Header("NAME").Value = CStr(oSOPRecord.Fields.Item("NAME").Value)
oSOPPost.Header("ADDRESS_1").Value = CStr(oSOPRecord.Fields.Item("ADDRESS_1").Value)
oSOPPost.Header("ADDRESS_2").Value = CStr(oSOPRecord.Fields.Item("ADDRESS_2").Value)
oSOPPost.Header("ADDRESS_3").Value = CStr(oSOPRecord.Fields.Item("ADDRESS_3").Value)
oSOPPost.Header("ADDRESS_4").Value = CStr(oSOPRecord.Fields.Item("ADDRESS_4").Value)
oSOPPost.Header("ADDRESS_5").Value = CStr(oSOPRecord.Fields.Item("ADDRESS_5").Value)
oSOPPost.Header("DEL_ADDRESS_1").Value = CStr(oSOPRecord.Fields.Item("DEL_ADDRESS_1").Value)
oSOPPost.Header("DEL_ADDRESS_2").Value = CStr(oSOPRecord.Fields.Item("DEL_ADDRESS_2").Value)
oSOPPost.Header("DEL_ADDRESS_3").Value = CStr(oSOPRecord.Fields.Item("DEL_ADDRESS_3").Value)
oSOPPost.Header("DEL_ADDRESS_4").Value = CStr(oSOPRecord.Fields.Item("DEL_ADDRESS_4").Value)
oSOPPost.Header("DEL_ADDRESS_5").Value = CStr(oSOPRecord.Fields.Item("DEL_ADDRESS_5").Value)
oSOPPost.Header("CUST_TEL_NUMBER").Value = CStr(oSOPRecord.Fields.Item("CUST_TEL_NUMBER").Value)
oSOPPost.Header("CONTACT_NAME").Value = CStr(oSOPRecord.Fields.Item("CONTACT_NAME").Value)
oSOPPost.Header("GLOBAL_TAX_CODE").Value = CShort(oSOPRecord.Fields.Item("GLOBAL_TAX_CODE").Value)
oSOPPost.Header("ORDER_DATE").Value = CDate(oSOPRecord.Fields.Item("ORDER_DATE").Value)
oSOPPost.Header("NOTES_1").Value = CStr(oSOPRecord.Fields.Item("NOTES_1").Value)
oSOPPost.Header("NOTES_2").Value = CStr(oSOPRecord.Fields.Item("NOTES_1").Value)
oSOPPost.Header("NOTES_3").Value = CStr(oSOPRecord.Fields.Item("NOTES_3").Value)
oSOPPost.Header("TAKEN_BY").Value = CStr(oSOPRecord.Fields.Item("TAKEN_BY").Value)
oSOPPost.Header("ORDER_NUMBER").Value = CStr(oSOPRecord.Fields.Item("ORDER_NUMBER").Value)
oSOPPost.Header("CUST_ORDER_NUMBER").Value = CStr(oSOPRecord.Fields.Item("CUST_ORDER_NUMBER").Value)
oSOPPost.Header("PAYMENT_REF").Value = CStr(oSOPRecord.Fields.Item("PAYMENT_REF").Value)
oSOPPost.Header("GLOBAL_NOM_CODE").Value = CStr(oSOPRecord.Fields.Item("GLOBAL_NOM_CODE").Value)
oSOPPost.Header("GLOBAL_DETAILS").Value = CStr(oSOPRecord.Fields.Item("GLOBAL_DETAILS").Value)
oSOPPost.Header("ORDER_TYPE").Value = oSOPRecord.Fields.Item("ORDER_TYPE").Value
oSOPPost.Header("FOREIGN_RATE").Value = CDbl(oSOPRecord.Fields.Item("FOREIGN_RATE").Value)
oSOPPost.Header("CURRENCY").Value = oSOPRecord.Fields.Item("CURRENCY").Value
oSOPPost.Header("CURRENCY_USED").Value = oSOPRecord.Fields.Item("CURRENCY_USED").Value
' Link header to items
oSOPItem_Read = oSOPRecord.Link
'Find the First Record
oSOPItem_Read.MoveFirst()
Do
'Add the existing items to the order
oSOPItem_Write = oSOPPost.Items.Add
'Populate the Fields, copying the data from the existing records
oSOPItem_Write.Fields.Item("STOCK_CODE").Value = CStr(oSOPItem_Read.Fields.Item("STOCK_CODE").Value)
oSOPItem_Write.Fields.Item("DESCRIPTION").Value = CStr(oSOPItem_Read.Fields.Item("DESCRIPTION").Value)
oSOPItem_Write.Fields.Item("NOMINAL_CODE").Value = CStr(oSOPItem_Read.Fields.Item("NOMINAL_CODE").Value)
oSOPItem_Write.Fields.Item("TAX_CODE").Value = CShort(oSOPItem_Read.Fields.Item("TAX_CODE").Value)
oSOPItem_Write.Fields.Item("QTY_ORDER").Value = CDbl(oSOPItem_Read.Fields.Item("QTY_ORDER").Value)
oSOPItem_Write.Fields.Item("UNIT_PRICE").Value = CDbl(oSOPItem_Read.Fields.Item("UNIT_PRICE").Value)
oSOPItem_Write.Fields.Item("NET_AMOUNT").Value = CDbl(oSOPItem_Read.Fields.Item("NET_AMOUNT").Value)
oSOPItem_Write.Fields.Item("TAX_AMOUNT").Value = CDbl(oSOPItem_Read.Fields.Item("TAX_AMOUNT").Value)
oSOPItem_Write.Fields.Item("COMMENT_1").Value = CStr(oSOPItem_Read.Fields.Item("COMMENT_1").Value)
oSOPItem_Write.Fields.Item("COMMENT_2").Value = CStr(oSOPItem_Read.Fields.Item("COMMENT_2").Value)
oSOPItem_Write.Fields.Item("UNIT_OF_SALE").Value = CStr(oSOPItem_Read.Fields.Item("UNIT_OF_SALE").Value)
oSOPItem_Write.Fields.Item("FULL_NET_AMOUNT").Value = CDbl(oSOPItem_Read.Fields.Item("FULL_NET_AMOUNT").Value)
oSOPItem_Write.Fields.Item("TAX_RATE").Value = CDbl(oSOPItem_Read.Fields.Item("TAX_RATE").Value)
'We now need to ensure that the TAX_FLAG is set the same as the item being read otherwise it will be re calculated
oSOPItem_Write.Fields.Item("TAX_FLAG").Value = CInt(oSOPItem_Read.Fields.Item("TAX_FLAG").Value)
'Loop until there are no more existing items
Loop Until oSOPItem_Read.MoveNext = False
'destroy the oSOPItem_Write object
oSOPItem_Write = Nothing
'write a new item
oStockRecord.MoveLast()
oSOPItem_Write = oSOPPost.Items.Add
' Populate other fields required for Invoice Item
' From 2015 the update method now wraps internal business logic
' that calculates the vat amount if a net amount is given.
' If you wish to calculate your own Tax values you will need
' to ensure that you set the TAX_FLAG to 1 and set the TAX_AMOUNT value on the item line
' ***Note if a NVD is set the item line values will be recalculated
' regardless of the Tax_Flag being set to 1***
oSOPItem_Write.Fields.Item("STOCK_CODE").Value = oStockRecord.Fields.Item("STOCK_CODE").Value
oSOPItem_Write.Fields.Item("DESCRIPTION").Value = CStr(oStockRecord.Fields.Item("DESCRIPTION").Value)
oSOPItem_Write.Fields.Item("NOMINAL_CODE").Value = CStr(oStockRecord.Fields.Item("NOMINAL_CODE").Value)
oSOPItem_Write.Fields.Item("TAX_CODE").Value = CShort(oStockRecord.Fields.Item("TAX_CODE").Value)
oSOPItem_Write.Fields.Item("QTY_ORDER").Value = CDbl(2)
oSOPItem_Write.Fields.Item("UNIT_PRICE").Value = CDbl(50)
oSOPItem_Write.Fields.Item("NET_AMOUNT").Value = CDbl(100)
oSOPItem_Write.Fields.Item("FULL_NET_AMOUNT").Value = CDbl(100)
oSOPItem_Write.Fields.Item("COMMENT_1").Value = CStr("")
oSOPItem_Write.Fields.Item("COMMENT_2").Value = CStr("")
oSOPItem_Write.Fields.Item("UNIT_OF_SALE").Value = CStr("")
oSOPItem_Write.Fields.Item("TAX_RATE").Value = CDbl(20)
'Destroy the oSOPItem_Write object
oSOPItem_Write = Nothing
'Post the order
If oSOPPost.Update() Then
MsgBox("Order Updated Successfully")
Else
MsgBox("Order Update Failed")
End If
'Disconnect and destroy the objects
oWS.Disconnect()
oSDO = Nothing
oWS = Nothing
oSOPRecord = Nothing
oSOPItem_Read = Nothing
oSOPItem_Write = Nothing
oSOPPost = Nothing
oStockRecord = Nothing
End If
Exit Sub
使用:
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
}
答案 9 :(得分:-1)
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