Swift: Immutable Struct Singleton Initialization

How can you initialize a struct singleton that has dependencies? You likely chose to use a struct because you’re trying to reduce state and keep things immutable in your code. You’re also likely wanting to use the singleton pattern for a shared service or model in your project.

I’m a fan of keeping things immutable if possible, and I default to structs and lets before using classes, or vars.

One place I’ll use this pattern is when making services that depend on an external API like so:

struct ApiClient {
    private let secret: String
    
    init(secret: String) {
        self.secret = secret
    }

    // ...
}

struct LoginService {
    private let apiClient: ApiClient
    
    static let shared: LoginService = {
        let apiClient = ApiClient(secret: "CLIENT_SECRET")
        return LoginService(apiClient: apiClient)
    }()

    // ...
}

Notice that LoginService is immutable (look Ma, no vars!), and we can be sure that our shared instance will always be the same instance when we call LoginService.shared.

Often, our shared assignment is more complex than this. For example, the secret here used to initialize the API Client in a more mature project would not be a magic string like we have here and can instead be dependent on launch arguments or an environment variable.