Singleton is a design pattern that ensures that a class has only one instance and provides a global point of access to that instance. In Swift, a Singleton class is implemented by creating a static constant instance within the class and using a private initializer to prevent any other instances from being created.
A common practical use case would be a Logger. Sometimes, print statements are not enough; you might want to log to a specific destination, or use different levels for example. If you are not using a proper DI mechanism, in order to avoid consuming unnecessary resources, a singleton would be an easy and quick way to share the same instance.
Some developers might advocate against using singletons, but they may not be able to clearly explain why. The problem is that singletons can make your code untestable by introducing global state. When an instance can be accessed by multiple parts of the application, it not only becomes difficult to understand the code, but also to predict its behavior. An alternative to avoid this issue is to use dependency injection.
As stated before, singletons are shared instances that can be accessed by multiple threads. There could be a problem if this same instance is accessed concurrently (by two or more threads at the same time) — that is called race condition. This can lead to, once again, unpredictable behavior and also deadlocks which can be fatal to the application. A solution for this is to use thread-safe techniques such as dispatch queue.