Swift
Programming
Number Formatting
iOS Development
Thousand Separator

Adding Thousand Separator to Int in Swift

Master System Design with Codemia

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

Introduction

The usual way to add thousand separators to an Int in Swift is to format the number rather than manually insert commas. NumberFormatter is the classic solution, and newer Swift versions also provide .formatted() for a shorter, more modern syntax.

Use NumberFormatter For Broad Compatibility

NumberFormatter is the standard Foundation API for locale-aware numeric formatting.

swift
1import Foundation
2
3let number = 1234567
4
5let formatter = NumberFormatter()
6formatter.numberStyle = .decimal
7
8if let result = formatter.string(from: NSNumber(value: number)) {
9    print(result)
10}

In an en_US locale this prints 1,234,567. In other locales it may use periods or spaces instead, which is exactly why formatter-based output is better than hard-coded string manipulation.

Control Locale And Grouping Rules

If the output must follow a specific locale, set it explicitly:

swift
1import Foundation
2
3let formatter = NumberFormatter()
4formatter.numberStyle = .decimal
5
6formatter.locale = Locale(identifier: "en_US")
7print(formatter.string(from: NSNumber(value: 1234567))!)
8
9formatter.locale = Locale(identifier: "de_DE")
10print(formatter.string(from: NSNumber(value: 1234567))!)
11
12formatter.locale = Locale(identifier: "fr_FR")
13print(formatter.string(from: NSNumber(value: 1234567))!)

This matters because "thousand separator" is really a locale-specific grouping separator. Some users expect commas, some expect periods, and some expect spaces.

You can also override the grouping separator manually, but that should be a deliberate formatting rule rather than a default assumption.

Use .formatted() In Newer Swift

On newer Apple platforms, integer types support .formatted() directly:

swift
1let number = 1234567
2
3print(number.formatted())
4print(number.formatted(.number.grouping(.automatic)))
5print(number.formatted(.number.locale(Locale(identifier: "de_DE"))))

This is concise and readable, and it still respects locale-aware number formatting rules.

If your deployment target includes older iOS or macOS versions, NumberFormatter remains the more compatible choice.

Edge Cases Still Matter

Formatting should still behave correctly for negative numbers, zero, and very large integers:

swift
print(0.formatted())
print((-1234567).formatted())
print(9876543210.formatted())

You generally do not need special-case code for these values if you use the formatter APIs correctly. That is another reason to avoid hand-written string insertion logic, which often breaks on minus signs or unusual grouping rules.

This also makes tests simpler because the same formatting path handles normal, negative, and large values consistently.

Reuse The Formatter In Real Code

One common mistake is creating a new NumberFormatter every time a value is rendered in a table, collection, or SwiftUI list. NumberFormatter is relatively expensive to create, so reuse it.

swift
1import Foundation
2
3enum Formatters {
4    static let groupedInteger: NumberFormatter = {
5        let formatter = NumberFormatter()
6        formatter.numberStyle = .decimal
7        return formatter
8    }()
9}
10
11extension Int {
12    var grouped: String {
13        Formatters.groupedInteger.string(from: NSNumber(value: self)) ?? "\(self)"
14    }
15}
16
17print(9876543.grouped)

This keeps formatting logic centralized and avoids repeated formatter allocation.

SwiftUI And String Interpolation

In SwiftUI, formatting can stay close to the view:

swift
1import SwiftUI
2
3struct CountView: View {
4    let count = 1234567
5
6    var body: some View {
7        VStack {
8            Text(count.formatted())
9            Text("Users: \(count.formatted(.number))")
10        }
11    }
12}

If you are not on a deployment target that supports .formatted(), a small helper that uses NumberFormatter works just as well.

Common Pitfalls

  • Inserting commas manually instead of using a locale-aware formatter.
  • Assuming every user expects commas as the grouping separator.
  • Creating a fresh NumberFormatter on every render path.
  • Forgetting that string(from:) returns an optional.
  • Using .formatted() without checking whether the deployment target supports it.

Summary

  • Use NumberFormatter with .decimal for a dependable, locale-aware thousand separator.
  • Use .formatted() when your Swift and platform versions support it.
  • Set the locale explicitly when the output format must be predictable.
  • Reuse formatters in performance-sensitive code instead of creating them repeatedly.

Course illustration
Course illustration

All Rights Reserved.