The aim of this post is to provide one of the many available methods for keeping secrets, such as passwords or API keys, out of your base code while still ensuring they are accessible during the development phase.
.env file
One common approach is to create a text file, usually named by convention as .env, although you are free to name it as you prefer. This file will contain the secrets of your project.

This is a keep-it-out-of-version-control
This is a medicine; keep out of reach of children version control system. So be sure that it is included in .gitignore.

Commit and push changes asap:


An important consideration is where to place the folder. It must be located in the same root directory where the source code begins.

If you have already committed and pushed the changes, anyone with access to your repository could potentially access that data. You have two alternatives:
- Use
git rebase
: Withgit rebase
, you can modify your commit history, allowing you to remove the problematic commit. This is a cleaner approach but requires careful handling to avoid conflicts. - Create a new repository: This option will result in the loss of your commit history but can be simpler if preserving history is not essential.
Additionally, remember that your .env
file is only stored locally on your machine. Ensure you keep it secure to prevent sensitive information from being exposed.
Lets play with XCode
Create a blank app project in XCode and be sure that following settings are set:

Swift Language version to Swift 6 and …

Strict Concurrency Checking is set to Complete, ensuring that our code, in addition to being secure and preventing disclosure of sensitive information, will also be free from data races. Finally, create a new file with the following component.
import Foundation
@globalActor
actor GlobalManager {
static var shared = GlobalManager()
}
@GlobalManager final class Env {
static let env: [String: String] = loadEnvVariables()
static let filename = ".env"
private init() {
}
static func fetch(key: String) -> String? {
env[key]
}
static func loadEnvVariables() -> [String: String] {
var envVariables: [String: String] = [:]
guard let path = Bundle.main.path(forResource: filename, ofType: nil) else {
return [:]
}
do {
let content = try String(contentsOfFile: path, encoding: .utf8)
let lines = content.components(separatedBy: .newlines)
for line in lines {
let components = line.components(separatedBy: "=")
if components.count == 2 {
let key = components[0].trimmingCharacters(in: .whitespaces)
let value = components[1].trimmingCharacters(in: .whitespaces)
envVariables[key] = value
}
}
} catch {
print("Error reading .env: \(error)")
}
return envVariables
}
}
Finally, use the Env component to fetch secret data from the .env file.
struct ContentView: View {
@State private var apiKey: String?
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("API_KEY:\(apiKey ?? "Not set")")
}
.padding()
.onAppear {
Task {
apiKey = await Env.fetch(key: "API_KEY")
}
}
}
}
This is the default ContentView
generated in a blank project. We have added content using the .onAppear()
modifier to fetch the secret, which is displayed with a Text
view. Run the project, and the final result is as follows:

Conclusions
This is a safe way to keep your project secrets away from indiscreet eyes. However, your secret file is only stored locally in your (or the developer team’s) project folder. On this repository is the source code that I have used for writing this post.
Related links
- Using environment variables in Swift
Swift on server
- ¡Adiós al patrón Singleton en clases en Swift 6!
Apple Coding Academy Post