Dear Erica: Singletons and Static Property Side Effects

Laptopmini writes, “Can you define a ‘get‘ closure for a singleton’s sharedInstance? I have a web socket manager and I’d like it to call ‘connect()‘ any time its instance is fetched”

A basic Swift singleton looks like this:

public final class Singleton {
    public static let shared = Singleton()
    private init() { }
}

This design creates a class with a single accessible shared instance. The class is marked final, and the initializer is private, ensuring the type cannot be subclassed or instantiated beyond shared.

To introduce side effects, create indirect access to the singleton and add your custom behavior to a getter:

public final class Singleton {
    private static let _shared = Singleton()
    private init() { }
    
    public static var shared: Singleton {
        get {
            print("side effects here")
            connect() // for example
            return _shared
        }
    }
}

This works but it’s a little more complicated than it has to be. As a get-only property, you can omit the get syntax. Just move the custom behavior to the top-level var clause, as in the following modification:

public final class Singleton {
    private static let _shared = Singleton()
    private init() { }
    
    public static var shared: Singleton {
        print("side effects here")
        connect() // for example
        return _shared
    }
}

Quick summary:

  • Use reference types for singletons.
  • Mark the type final, the instance public, and the initializer private.
  • When naming, prefer the Swiftier shared to the more Objective-C sharedInstance.
  • Create a static getter for any side effects.
  • Omit the get syntax for get-only properties.

Have some thoughts about improving this? As always, drop a note in the comments or tweet me and I’ll tweak.

Rob N has a good point here:

Comments are closed.