Swift
iOS Development
Currency Symbols
Programming
Code Conversion

Get currency symbols from currency code with swift

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

To get a currency symbol (like $, , £) from a currency code (like USD, EUR, GBP) in Swift, use Locale and NumberFormatter from the Foundation framework. The approach is to find a locale that uses the given currency code, then extract its currencySymbol. Since one currency code can map to multiple locales (e.g., USD is used in en_US, es_US, and others), you typically pick the first matching locale or a specific one. NumberFormatter can also format amounts with the correct symbol and placement for any locale.

Basic Currency Symbol Lookup

swift
1import Foundation
2
3func currencySymbol(for code: String) -> String? {
4    let locales = Locale.availableIdentifiers
5    for identifier in locales {
6        let locale = Locale(identifier: identifier)
7        if locale.currency?.identifier == code {
8            return locale.currencySymbol
9        }
10    }
11    return nil
12}
13
14print(currencySymbol(for: "USD") ?? "?")  // $
15print(currencySymbol(for: "EUR") ?? "?")  // €
16print(currencySymbol(for: "GBP") ?? "?")  // £
17print(currencySymbol(for: "JPY") ?? "?")  // ¥
18print(currencySymbol(for: "INR") ?? "?")  // ₹

Optimized with Dictionary Cache

swift
1import Foundation
2
3class CurrencyHelper {
4    static let shared = CurrencyHelper()
5
6    private let symbolMap: [String: String]
7
8    private init() {
9        var map: [String: String] = [:]
10        for identifier in Locale.availableIdentifiers {
11            let locale = Locale(identifier: identifier)
12            if let code = locale.currency?.identifier,
13               let symbol = locale.currencySymbol,
14               map[code] == nil {
15                map[code] = symbol
16            }
17        }
18        self.symbolMap = map
19    }
20
21    func symbol(for currencyCode: String) -> String {
22        return symbolMap[currencyCode] ?? currencyCode
23    }
24}
25
26// Usage
27print(CurrencyHelper.shared.symbol(for: "USD"))  // $
28print(CurrencyHelper.shared.symbol(for: "BRL"))  // R$
29print(CurrencyHelper.shared.symbol(for: "KRW"))  // ₩
30print(CurrencyHelper.shared.symbol(for: "XYZ"))  // XYZ (fallback)

Using NumberFormatter

NumberFormatter formats amounts with the correct symbol, placement, and decimal separator:

swift
1import Foundation
2
3func formatCurrency(amount: Double, currencyCode: String,
4                    locale: Locale = .current) -> String {
5    let formatter = NumberFormatter()
6    formatter.numberStyle = .currency
7    formatter.currencyCode = currencyCode
8    formatter.locale = locale
9    return formatter.string(from: NSNumber(value: amount)) ?? "\(amount)"
10}
11
12// Format with user's locale
13print(formatCurrency(amount: 1234.56, currencyCode: "USD"))
14// US locale: $1,234.56
15// German locale: 1.234,56 $
16
17// Force a specific locale
18print(formatCurrency(amount: 1234.56, currencyCode: "EUR",
19                     locale: Locale(identifier: "de_DE")))
20// 1.234,56 €
21
22print(formatCurrency(amount: 1234.56, currencyCode: "JPY",
23                     locale: Locale(identifier: "ja_JP")))
24// ¥1,235 (JPY has no decimal places)

Getting Just the Symbol from NumberFormatter

swift
1func currencySymbolViaFormatter(for code: String) -> String {
2    let formatter = NumberFormatter()
3    formatter.numberStyle = .currency
4    formatter.currencyCode = code
5
6    // Format zero, then strip the number and whitespace
7    let formatted = formatter.string(from: 0) ?? code
8    let symbol = formatted.replacingOccurrences(
9        of: "[\\d.,\\s]",
10        with: "",
11        options: .regularExpression
12    )
13    return symbol.isEmpty ? code : symbol
14}
15
16print(currencySymbolViaFormatter(for: "USD"))  // $
17print(currencySymbolViaFormatter(for: "GBP"))  // £
18print(currencySymbolViaFormatter(for: "THB"))  // ฿

Locale-Aware Symbol Display

The same currency code produces different symbols depending on the locale:

swift
1let locales = ["en_US", "en_GB", "de_DE", "ja_JP", "fr_FR"]
2let currencyCode = "USD"
3
4for id in locales {
5    let locale = Locale(identifier: id)
6    let formatter = NumberFormatter()
7    formatter.numberStyle = .currency
8    formatter.currencyCode = currencyCode
9    formatter.locale = locale
10
11    let formatted = formatter.string(from: 1234.56) ?? ""
12    print("\(id): \(formatted)")
13}
14// en_US: $1,234.56
15// en_GB: US$1,234.56
16// de_DE: 1.234,56 $
17// ja_JP: $1,234.56
18// fr_FR: 1 234,56 $US

Note how en_GB uses US$ to disambiguate from £, and fr_FR uses $US with different number formatting.

Common Currency Codes and Symbols

CodeSymbolCurrency
USD
EUREuro
GBP£British Pound
JPY¥Japanese Yen
CNY¥Chinese Yuan
KRWSouth Korean Won
INRIndian Rupee
BRL
RUBRussian Ruble
THB฿Thai Baht

SwiftUI Integration

swift
1import SwiftUI
2
3struct PriceView: View {
4    let amount: Double
5    let currencyCode: String
6
7    var body: some View {
8        Text(formattedPrice)
9            .font(.headline)
10    }
11
12    private var formattedPrice: String {
13        let formatter = NumberFormatter()
14        formatter.numberStyle = .currency
15        formatter.currencyCode = currencyCode
16        formatter.locale = .current
17        return formatter.string(from: NSNumber(value: amount)) ?? "\(amount)"
18    }
19}
20
21struct CurrencyListView: View {
22    let currencies = ["USD", "EUR", "GBP", "JPY", "INR"]
23
24    var body: some View {
25        List(currencies, id: \.self) { code in
26            HStack {
27                Text(CurrencyHelper.shared.symbol(for: code))
28                    .font(.title)
29                    .frame(width: 50)
30                Text(code)
31                Spacer()
32                PriceView(amount: 99.99, currencyCode: code)
33            }
34        }
35    }
36}

Handling Edge Cases

swift
1// Currencies with no decimal places
2let formatter = NumberFormatter()
3formatter.numberStyle = .currency
4formatter.currencyCode = "JPY"
5print(formatter.string(from: 1000)!)  // ¥1,000 (no decimals)
6
7formatter.currencyCode = "KWD"  // Kuwaiti Dinar uses 3 decimal places
8print(formatter.string(from: 1.234)!)  // KWD 1.234
9
10// Handling nil/unknown currency codes
11func safeSymbol(for code: String?) -> String {
12    guard let code = code, !code.isEmpty else { return "?" }
13    return CurrencyHelper.shared.symbol(for: code)
14}

Common Pitfalls

  • Iterating all locales on every lookup: Locale.availableIdentifiers contains hundreds of entries. Iterating it for every symbol lookup is slow. Build a dictionary cache once (as shown in CurrencyHelper) and reuse it throughout the app.
  • Assuming $ always means USD: Many currencies use $ (USD, CAD, AUD, NZD, SGD). In non-US locales, $ may refer to the local dollar. Use the full currency code alongside the symbol for clarity, or let NumberFormatter handle disambiguation.
  • Hardcoding decimal places for currencies: JPY uses 0 decimal places, KWD uses 3, and most others use 2. NumberFormatter with .currency style handles this automatically. Never format currency amounts with a fixed 2-decimal format.
  • Ignoring locale differences in symbol placement: Some locales place the symbol before the amount ($100), others after (100 €), and some use different decimal/grouping separators. Always use NumberFormatter for display rather than string concatenation like "$" + amount.
  • Using Locale.current in unit tests: Locale.current depends on the device/simulator settings and changes between machines. Pass Locale as a parameter in functions you test, and use a fixed locale like Locale(identifier: "en_US") in tests for consistent results.

Summary

  • Use Locale.availableIdentifiers to find a locale matching a currency code, then access currencySymbol
  • Cache the code-to-symbol mapping in a dictionary for performance
  • Use NumberFormatter with .currency style for properly formatted amounts with correct symbols, decimal places, and placement
  • The same currency code renders differently depending on locale — always use NumberFormatter for user-facing display
  • Build a CurrencyHelper singleton to provide fast symbol lookups across your app

Course illustration
Course illustration

All Rights Reserved.