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 struct
s and let
s before using class
es, or var
s.
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 var
s!), 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.