iOS development
global constants
best practices
Swift programming
application architecture

Where to store global constants in an iOS application?

Master System Design with Codemia

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

Introduction

There is no single magic file for "global constants" in an iOS app. The best location depends on what the value represents: compile-time constants belong in code, environment-specific settings often belong in configuration files, and secrets should usually not live in plain source at all.

The simplest pattern: namespace constants in a type

For most app code, a dedicated namespace type is the cleanest approach. In Swift, that usually means a struct or enum with static members.

swift
1enum AppConstants {
2    static let defaultAnimationDuration: TimeInterval = 0.25
3    static let supportEmail = "[email protected]"
4}
5
6enum API {
7    static let baseURL = URL(string: "https://api.example.com")!
8    static let timeout: TimeInterval = 10
9}

This keeps related values grouped, discoverable, and type-safe. It also avoids polluting the global namespace with free-floating constants.

Group by domain, not by "all constants"

A giant Constants.swift file works for tiny apps, but it becomes a junk drawer in real projects. A better approach is to group values by feature or responsibility:

  • 'API.swift for networking endpoints and headers'
  • 'DesignTokens.swift for colors, spacing, and typography'
  • 'FeatureFlags.swift for temporary switches'
  • 'Notifications.swift for names and keys'

That makes constants easier to find and reduces accidental coupling between unrelated areas of the app.

Use asset catalogs and localized files where appropriate

Not everything that stays constant should live in Swift code.

If the value is a color, image, or symbol, prefer asset catalogs. If it is user-facing text, prefer localization files. If it changes by build environment, consider xcconfig files or Info.plist values.

For example, environment-specific settings can be read from the bundle:

swift
1enum BuildConfig {
2    static let apiBaseURL: String = {
3        guard let value = Bundle.main.object(forInfoDictionaryKey: "API_BASE_URL") as? String else {
4            fatalError("Missing API_BASE_URL")
5        }
6        return value
7    }()
8}

That is better than hard-coding a staging URL directly in app logic if the value changes between builds.

Avoid storing secrets as constants

API keys, private tokens, and signing credentials are not ordinary constants. If you put them in source files, they are easy to leak through version control or reverse engineering.

For client apps, assume anything shipped inside the app bundle can be extracted. If a value must be protected, move the sensitive logic to a backend or use a mechanism designed for credentials, such as Keychain for runtime storage.

In other words, "constant" and "safe to hard-code" are not the same thing.

When top-level constants are acceptable

Swift supports top-level let declarations, and they can be fine for a very small module:

swift
let maxRetryCount = 3
let animationDuration: TimeInterval = 0.25

But in shared app code, namespaced constants are usually clearer because they reduce collision risk and make intent easier to discover from autocomplete.

Constants versus computed configuration

Some values look constant but really come from the current environment, locale, or device. Those should not be modeled as static constants if they can change.

For example, the current locale, screen scale, and feature-flag state are runtime values. Treating them as compile-time constants makes the architecture less honest and harder to test.

Common Pitfalls

  • Putting every fixed value into one massive Constants.swift file.
  • Hard-coding environment-specific values that should come from build configuration.
  • Storing secrets in source control because they "never change".
  • Using global top-level constants so widely that naming collisions become likely.
  • Treating runtime configuration as if it were a real compile-time constant.

Summary

  • Store most app-wide constants in namespaced Swift types with static members.
  • Group constants by domain rather than by one giant file.
  • Use assets, localization files, Info.plist, or xcconfig where those tools fit better than code.
  • Do not treat secrets as ordinary constants.
  • Prefer a structure that makes constants easy to find and hard to misuse.

Course illustration
Course illustration

All Rights Reserved.