I want to use the singleton pattern in my class which has a private init with parameter. It also has a class function called setup which configures
A simplified version of different answers; but without any force unwraps, not having shared as a func and having the possibility to have a config. It doesn't need to be more complicated then this, which works well with Swift 5:
import UIKit
final class ParameterSingleton {
static var shared: ParameterSingleton {
if let initializedShared = _shared {
return initializedShared
}
fatalError("Singleton not yet initialized. Run setup(withConfig:) first")
}
private static var _shared: ParameterSingleton? // This can only be set by the setup() func since it is private
private var config: ParameterSingletonConfig // The configuration for the singleton. Could be a `String` if so requested
/// The ParameterSingleton setup func. Will initialize the singleton with the config. Without a config, `shared` will cause a `fatalError`
///
/// - Parameter config: The config needed for initializing the singleton
class func setup(withConfig config: ParameterSingletonConfig) {
_shared = ParameterSingleton(withConfig: config)
}
// Make the init private so this class can only be used be invoking the `setup(withConfig:)` func
private init(withConfig config: ParameterSingletonConfig) {
self.config = config
}
/// The public func to do something
func doSomething() {
print("Config URL: \(config.url)")
}
}
struct ParameterSingletonConfig {
let url: String
}
//Will cause fatalError
ParameterSingleton.shared.doSomething()
//Will not cause fatalError
ParameterSingleton.setup(withConfig: ParameterSingletonConfig(url: "http://www.google.com"))
ParameterSingleton.shared.doSomething()
Of course, if you only need to set one parameter, you could remove ParameterSingletonConfig and replace it with a String instead