Running Turtle Running Turtle - 7 months ago 8
Swift Question

What's the difference between Struct based and Class based singletons?

Are the two approaches the same or are there major differences/pitfalls to be aware of:

class MyClassSingleton {
static let sharedInstance = MyClassSingleton()
private init(){}

func helloClass() { print("hello from class Singleton") }
}

struct MyStructSingleton {
static let sharedInstance = MyStructSingleton()
private init() {}

func helloStruct() { print("hello from struct Singleton") }
}

Answer

The main difference is that class-based mutable singleton works, while struct-based mutable "singleton" doesn't. Unless you want to make your singleton immutable (which is rare) you should stick to the class-based one.

Here is an illustration of how mutable struct-based "singleton" does not work. Consider adding a mutable member state to both singletons, like this:

class MyClassSingleton {
    static let sharedInstance = MyClassSingleton()
    private init(){}
    var state = 5;
    func helloClass() { print("hello from class Singleton: \(state)") }
}

struct MyStructSingleton {
    static let sharedInstance = MyStructSingleton()
    private init() {}
    var state = 5;
    func helloStruct() { print("hello from struct Singleton: \(state)") }
}

I made state a var, but I could expose it as a read-only property plus a mutating method; the essential thing is that both types are now mutable.

If I do this

let csi = MyClassSingleton.sharedInstance
csi.state = 42
MyClassSingleton.sharedInstance.helloClass()

42 gets printed, because csi is referencing the shared instance.

However, when I do the same thing with struct-based singleton

var ssi = MyStructSingleton.sharedInstance
ssi.state = 42
MyStructSingleton.sharedInstance.helloStruct()

5 gets printed instead, because ssi is a copy of the sharedInstance, which is, of course, an indication that our singleton is not actually a singleton.

Comments