Singleton and init with parameter

I have a slightly different solution.
This relies on

  1. Static variable is lazily initialised
  2. Using a Config struct to store the initialisation params
  3. Enforcing the setup call with a fatalError in init
    (if the setup call isn’t called before accessing the singleton)

.

class MySingleton {

    static let shared = MySingleton()
    
    struct Config {
        let param:String
    }
    private static var config:Config?
    
    class func setup(_ config:Config){
        MySingleton.config = config
    }
    
    private init() {
        guard let config = MySingleton.config else {
            fatalError("Error - you must call setup before accessing MySingleton.shared")
        }
        
        //Regular initialisation using config
    }
}

To use this, you set it up with

MySingleton.setup(MySingleton.Config(param: "Some Param"))

(Obviously you can use multiple params if needed by expanding the MySingleton.Config struct)

Then to access the singleton, you use

MySingleton.shared

I’m not wild about having to use a separate setup struct, but I like that this stays close to the recommended singleton pattern. Keeping the setup struct inside the singleton keeps things fairly clean.

Note – the shared object is a singleton. In the background, swift uses dispatchOnce to guarantee that. However there is nothing stopping you from calling setup multiple times with different configs from different threads.

At the moment, the first call to shared will ‘lock’ the setup.

If you want to lock things down after the first call to setup, then just call

_ = MySingleton.shared

in setup

Simple Example:

class ServerSingleton {
    static let shared = ServerSingleton()
    
    struct Config {
        let host:String
    }
    private static var config:Config?
    
    let host:String
    
    class func setup(_ config:Config){
        ServerSingleton.config = config
    }
    
    private init() {
        guard let config = ServerSingleton.config else {
            fatalError("Error - you must call setup before accessing MySingleton.shared")
        }
        
        host = config.host
    }
    
    func helpAddress() -> String {
        return host+"/help.html"
    }
}

ServerSingleton.setup(ServerSingleton.Config(host: "http://hobbyistsoftware.com") )
let helpAddress = ServerSingleton.shared.helpAddress()
//helpAddress is now http://hobbyistsoftware.com/help.html

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)