July 18, 2019

Create a Singleton with Swift

Learn how to easily create a singleton. Singletons can be quite controversial, but you should still know how to create one.

Create a Singleton with Swift

Today I will show you how to create a singleton with Swift. Singletons are a very touchy subject when it comes to programming. Personally I do not have an issue with them as long as it is used appropriately.

Why use a Singleton

The use case for a singleton is relatively small. The very few places where singletons can be used is when they are immutable or when they are one way.

What I mean by one way is that the information flows from your logic to somewhere else, it does not come back to your logic. A logger is a good example of this. When you want to log something you will tell the singleton what to log and it will log it. This is not an issue as nothing is returned and you do not need any information back from the logger.

Immutable situations could be where you need to do a certain calculation. If that calculation only relies on the arguments that gets passed in, then there will be no issue as it will not be relying on any state of the singleton.

Why do people dislike Singletons

Global state

Global state is bad because it can get changed at any time. The problem with this is that if there are multiple objects that rely on that state and any one of those objects can change the state at any time then it makes the program unpredictable because you do not know what the starting state was.

This can introduce some major bugs into the program and at the same time making it difficult to debug as you will have no idea what has changed the state or when it was changed.

Tightly coupled code

Tightly coupled code is when one piece of code relies on another piece of code, and it cannot work without that code. Code will generally have dependencies but there are different ways to go about handling those dependencies. People generally use a singleton directly, this causes their code to be tightly coupled to that singleton. If that singleton needs to be updated or removed, the change to the codebase could be huge.

They can make testing more difficult

This will depend on depend on what is being done with the singleton and how it is being used. Generally the issue is that the singleton creates itself.

The problem with this is that one cannot test it easily, or at all. The reason this makes it difficult to test is because one cannot substitute different implementations. For testing you might want an implementation that is used for testing and not to be using live/staging code. But when a singleton creates itself, you cannot use a different implementation.

How to create a Singleton in Swift

Finally we can get started with implementing a singleton. The basic idea of a singleton is for it to create an instance of itself. Generally this means that the initializer will be private and you will access the instance via a static property on the class.

Lets see what that looks like:

class Singleton {
    static let instance = Singleton()
    
    private init() {
        // Code here
    }
}

That will be the basis of our singleton. We have a private initializer and a static constant that we use. This constant will create only one instance of Singleton.

Lets test this out to make sure that it is working as expected. To do this we will add another function that will print a message to the console, and we will update the initializer to print out everytime it gets called.

class Singleton {
    static let instance = Singleton()
    
    private init() {
        print("Initialize the singleton")
    }
    
    func log(message: String) {
        print("Log: ", message)
    }
}

This code will now print out everytime the Singleton class has been initialized. We have also added code that will log a message to the console.

Lets use the above code. To do this we will access the instance property and call the methods from that instance property.

Singleton.instance.log(message: "This is a test message")
Singleton.instance.log(message: "Another message")

When you run the to lines above you should see an output like the below output:

Initialize the singleton
Log:  This is a test message
Log:  Another message

The output proves that the instance is only created once. The first time we access the instance property it will create a new instance of the Singletonclass. When we access the instance property for a second time it does not create a new instance, so we only see the message that we have logged.

When to use a Singleton

To know when to use a singleton just follow the reasons that I have mentioned in terms of Why use a singleton. Only choose to use a singleton if it is immutable, or if it is used for one way logic, i.e something like logging.

Conclusion

Singletons can be very useful but they are dangerous to use. Singletons mostly get abused and that is what has made people dislike them. Generally if you need to use a singleton you are probably doing something wrong and you should think more carefully about how to go about implementing what you want to implement. Dependency injection is one solution to the issue. That being said there are use cases for singletons, just make sure that your use case is valid one.