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.
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.swiftfor networking endpoints and headers' - '
DesignTokens.swiftfor colors, spacing, and typography' - '
FeatureFlags.swiftfor temporary switches' - '
Notifications.swiftfor 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:
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:
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.swiftfile. - 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
xcconfigwhere 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.

