Money is a Swift framework for iOS, watchOS, tvOS and OS X. It provides types and functionality to represent, calculate and convert money in the 298 ISO currencies.
The Money framework defines the type
Money, which represents money in the device’s current locale. The following code:
import Money let money: Money = 100 print("I'll give \(money) to charity.”)
will print out
I'll give $100.00 to charity
when the region is set to United States
I'll give £100.00 to charity
when the region is set to United Kingdom
I'll give CN¥100.00 to charity
when the region is set to China
You get the idea. See Localized Formatting for more info.
FloatLiteralConvertible. Which means values can be initialized using literal
Doubles as shown in these code snippets.
Under the hood,
Money is a
Currency.Local is a specific
CurrencyType which represents the currency for the current locale. This means that it is strongly typed to the local currency.
In a similar way, there are 298 foreign currency types supported.
let pounds: GBP = 99.99 let euros: EUR = 149.50 print(“You have \(pounds / 2) and \(euros + 30)”)
You have £ 50.00 and € 179.50
Because the currencies are typed, it means that they cannot be combined together.
let money = pounds + euros
Binary operator '+' cannot be applied to operands of type 'GBP' (aka '_Money<Currency.GBP>') and 'EUR' (aka '_Money<Currency.EUR>')
Money supports the usual suspects of decimal arithmetic operators, so you can add, subtract, multiply, divide values of the same type, and values with
Double with the expected limitations.
Money (and its friends) can be initialized with
Ints (and friends) and
let anIntegerFromSomewhereElse: Int = getAnInteger() let money = Money(anIntegerFromSomewhereElse) let aDoubleFromSomewhere: Double = getAnotherDouble() let pounds = GBP(aDoubleFromSomewhere)
Money can be initialized using the smallest units of currency:
let dollars = USD(minorUnits: 3250) let yuen = JPY(minorUnits: 3000) print(“You have \(dollars) and \(yuen)”)
You have $32.50 and ¥3,000
When displaying money values, it is important that they be correctly localized for the user. In general, it’s best to use the
Money type to always work in currency of the user’s current locale.
When printing a
MoneyType value, the
.description uses the current locale with
.CurrencyStyle number style, in conjunction with
NSNumberFormatter. The code snippets throughout this README uses
.description whenever the value of money is printed.
However, to specify a different style for the number formatter, use the
formattedWithStyle method, like this:
let money: Money = 99.99 print("She has \(money.formattedWithStyle(.CurrencyPluralStyle))")
For an American in Russia, this would print out:
She has 99,99 Russian roubles
Working with Locales
A locale is the codification of associated regional and linguistic attributes. A locale varies by language and region. Each locale has an identifier, which is the concatenation of language, country and modifier codes.
The language code is two or three lowercase letters. English is
en, French is
fr. There is a long list. Some languages are spoken in more than one country, in which case a country code (two uppercase letters) is appended (with an underscore). For example, English in the United States is
en_US, which is the default locale in the iOS Simulator. English in the United Kingdom is
Lastly, a locale identifier can be modified, say for example to set the currency code to “USD”, for Portuguese speaking user in Brazil, the locale identifier would be
NSLocale has support for ~ 730 distinct locales. Typically when creating a specific
NSLocale it is done with the locale identifier. The
NSLocale is like a dictionary with an
objectForKey method which returns
Formatting for specific Locale
NSLocale is an amazing class, but it’s very easy to make mistakes, and not that easy to construct. Therefore, to support arbitrary locales, but remove the need for framework consumers to construct locale identifiers, a new
Locale type is provided. This is an enum which means that it is type safe, and indexable for code completion in Xcode. Its cases are all the languages which
NSLocale supports. For those languages which are spoken in more than one country, there is an associated value of country names of only those counties.
To format money for a specific locale we can use the
Locale enum. The following code uses
Locale.Chinese(.China) to represent the
let money: Money = 99.99 print("She has \(money.formattedWithStyle(.CurrencyPluralStyle, forLocale: .Chinese(.China)))")
Now, for our American in Russia, (or any user with a region set to Russia) we get:
She has 99.99俄罗斯卢布
In this case, because our type is
Money, and the user’s region is set to Russia, we’re working with
RUB currency. But equally, if we need money in a specific currency, we can. Here’s Australian dollars, for a SwissGerman speaking user, in France.
let dollars: AUD = 39.99 print("You’ll need \((dollars / 2.5).formattedWithStyle(.CurrencyPluralStyle, forLocale: .SwissGerman(.France)))")
Regardless of the user’s current locale, this will print out:
You’ll need 16.00 Auschtralischi Dollar
On iOS (not watchOS, tvOS or OS X), there is support in Money for using
Money with Pay.
PaymentSummaryItem in lieu of
PKPaymentSummaryItem with a suitable
import PassKit typealias DollarItem = PaymentSummaryItem<USD> let items = [ DollarItem(label: "Something fancy.", cost: 9.99), DollarItem(label: "Something less fancy.", cost: 5.99) ] let request = PKPaymentRequest(items: items, sellerName: "Acme, Inc.")
The convenience initializer receives an array of
PaymentSummaryItem values and a seller name. It sets the currency code and payment summary items. Following the Pay guidelines, will append a total summary item using the provided seller name.
PaymentSummaryItem conforms to
Money has support for Bitcoin types, the popular
BTC and the unofficial ISO 4217 currency code
In November 2015, the Unicode consortium accepted U+20BF as the Bitcoin symbol. However, right now that means it is not available in Foundation. Therefore, currently the Bitcoin currency type(s) use Ƀ, which is also a popular symbol and available already within Unicode.
To work with Bitcoin, use the following:
let bitcoin: BTC = 0.1234_5678 print(“You have \(bitcoin)”)
You have Ƀ0.12345678
Foreign Exchange (FX)
The FX support which was previously part of this framework has been moved into its own, called FX.
Creating custom currencies
If your app has its own currency e.g. ⭐️s or