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 instancepublic
, and the initializerprivate
. - When naming, prefer the Swiftier
shared
to the more Objective-CsharedInstance
. - 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:
@ericasadun Nice article, but use case worries me. Means self.websocket may behave differently than Websocket.shared, even if same object.
— Rob Napier (@cocoaphony) January 5, 2017
Comments are closed.