← Back to list

Swift Data Formatting in Large Projects: Best Practices

Handling data formatting in large Swift projects can quickly become challenging when different parts of the application require different…

Sasikumar in Towards Dev · 2025-01-29 14:00 · 0 claps · 2.4 min read paywalled
#swift-tutorial #swift-enums-explained #ios-app-development #swiftbestpractices #swift-coding
Open on Medium ↗
Wiki topics: 💻 · Programming 📱 · Mobile Development

Swift Data Formatting in Large Projects: Best Practices

Photo by Isaac Martin on Unsplash

Photo by Isaac Martin on Unsplash

Handling data formatting in large Swift projects can quickly become challenging when different parts of the application require different formats while still needing consistency across multiple areas. A well-structured approach ensures maintainability, reduces redundancy, and improves overall code quality.

Challenges in Data Formatting

In large projects, data formatting can be inconsistent due to:

  1. Multiple formats in different contexts — Date and number formats may vary between UI displays, API responses, and storage.
  2. Repeated implementation — Formatting logic might be duplicated across different modules.
  3. Locale and Timezone handling — Global applications require localization support for formatting.
  4. Code maintenance issues — Hardcoded formats make modifications difficult and error-prone.

To overcome these challenges, adopting a structured and reusable approach to data formatting is essential.

Best Practices for Data Formatting

1. Avoiding Singletons for Formatting

While a singleton may seem like a good approach to centralizing formatting, it can introduce unintended global state and make testing difficult. Instead, prefer dependency injection or static utilities.

2. Using a Dedicated Formatting Utility

Instead of formatting data in multiple places, create a dedicated utility that handles all formatting logic. However, avoid using a singleton.

Example:

import Foundation

struct FormatterUtility {
    let dateFormatter: DateFormatter
    let numberFormatter: NumberFormatter

    init(dateFormat: String = "yyyy-MM-dd HH:mm:ss") {
        self.dateFormatter = DateFormatter()
        self.dateFormatter.dateFormat = dateFormat

        self.numberFormatter = NumberFormatter()
        self.numberFormatter.numberStyle = .decimal
    }

    func formatDate(_ date: Date) -> String {
        return dateFormatter.string(from: date)
    }

    func formatNumber(_ number: Double) -> String {
        return numberFormatter.string(from: NSNumber(value: number)) ?? ""
    }
}

Now, inject an instance where needed instead of relying on a shared global instance:

let formatter = FormatterUtility()
print(formatter.formatDate(Date()))
print(formatter.formatNumber(12345.678))

3. Using Extensions for Code Reusability

Extensions make it easier to format data directly on native types without cluttering the codebase.

Example:

extension Date {
    func formattedString(using formatter: FormatterUtility) -> String {
        return formatter.formatDate(self)
    }
}

extension Double {
    func formattedString(using formatter: FormatterUtility) -> String {
        return formatter.formatNumber(self)
    }
}

Now, formatting can be done more elegantly:

let formatter = FormatterUtility()
let currentDate = Date()
print(currentDate.formattedString(using: formatter))

let value = 12345.678
print(value.formattedString(using: formatter))

4. Handling Multiple Formats Using Enum

Different parts of the app might require different date formats. Enums help in handling this flexibly.

Example:

enum DateFormat: String {
    case full = "yyyy-MM-dd HH:mm:ss"
    case short = "dd/MM/yyyy"
    case timeOnly = "HH:mm"
}

extension Date {
    func formattedString(using format: DateFormat) -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = format.rawValue
        return formatter.string(from: self)
    }
}

Now, formatting a date based on context is easy:

let date = Date()
print(date.formattedString(using: .full))
print(date.formattedString(using: .short))

5. Localization Support

Supporting multiple locales ensures a smooth experience for global users.

Example:

extension NumberFormatter {
    static func localizedCurrencyFormatter(for locale: Locale) -> NumberFormatter {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = locale
        return formatter
    }
}

let price = 1234.56
let formatter = NumberFormatter.localizedCurrencyFormatter(for: Locale(identifier: "fr_FR"))
print(formatter.string(from: NSNumber(value: price)) ?? "")

6. Avoid Hardcoding Formats

Always store frequently used formats in a central place (like an enum or constants file) to avoid duplication and errors when updating formats globally.

Example:

struct Constants {
    struct DateFormat {
        static let standard = "yyyy-MM-dd HH:mm:ss"
        static let short = "dd/MM/yyyy"
    }
}

Final Thoughts

By implementing centralized formatting utilities without singletons, using extensions, supporting multiple formats via enums, handling localization, and avoiding hardcoded values, large Swift projects can maintain consistency and reduce code duplication. Using dependency injection instead of singletons ensures better flexibility and testability, leading to a more scalable and maintainable approach to data formatting across the entire application.


메타데이터
post_id
fb0d29cac46c
slug
swift-data-formatting-in-large-projects-best-practices-fb0d29cac46c
url
https://towardsdev.com/swift-data-formatting-in-large-projects-best-practices-fb0d29cac46c
canonical_url
https://towardsdev.com/swift-data-formatting-in-large-projects-best-practices-fb0d29cac46c
author_url
https://medium.com/@sasicse990
status
ok
fetched_at
2026-07-31 00:41:58