Join Scott Gardner for an in-depth discussion in this video Work with singletons, part of Swift 3 Essential Training: Beyond the Basics.
- [Instructor] A Singleton is an instance of a class that is instantiated only once. Maybe it's computationally expensive to create, or so widely used in a program that it just makes sense to keep it around in a global context. To define a Singleton class, first create a static property with a default value equal to an instance of itself, then make all of its initializers private. I'm going to cover access control later in the course. Basically, this private keyword restricts access to this initializer to the enclosing entity, that is, the Singleton class itself.
In other words, it cannot be called externally. If I try to access the initializer outside of the class, I'll get an error. The only way to access the shared instance of the class is via its shared static property. I'll also add a property to Singleton with a default value.
Now if I assign singletonA a value of A, and then I define a singletonB equal to Singleton.shared and set its value to B, I've actually created two references to the same instance. So singletonA.value is equal to singletonB.value because singletonA is singletonB. What if you want to define properties of a Singleton without assigning default values? Well I'm glad you asked.
I'll re-implement Counter from the previous video as a Singleton class. Instead of returning the shared instance via a static property, I'm going to implement a function, so I'll want to define the shared static instance as private. I'll also define a total property. Once again, I'll make my initializer private, but this time I'll include a startingWith parameter and set total to that value.
I'll also then want to set the static instance property to self. Having marked both the instance and the initializer as private, there's no way to access them externally, so I'll define a function shared that takes a total property with a default value of zero and returns a Counter instance. In it, I'll switch on the instance property. I'll define a case for if the instance property is not nil using optional pattern syntax that will unwrap an optional if it's not nil, and otherwise, I'll create a new instance of Counter with a starting total and assign it to instance, and then return the instance.
I'll finish off this implementation by defining increment and reset methods. Notice that, unlike for a structure, you do not mark a method that mutates self in a class as mutating.
Now I'll create a counterA instance of Counter using the shared method without passing parameters, which means its total will start at the default value I defined of zero, and I'll define a counterB value, this time setting the total to 10. Sure enough, counterA and counterB's total values are equal because counterA and counterB are pointing to the exact same instance. Another improvement in this implementation of Counter versus the struck version I defined in the last video is, there's no issue with chaining mutating methods on a class instance.
- Adding source files, resources, links, and literals
- Adding pages to a playground
- Using overflow operators and bitwise operators
- Using ranges with strings
- Creating complex sequences
- Chaining higher-order functions
- Defining lazy properties
- Using failable initializers
- Mutating methods
- Working with singletons
- Nesting function types
- Creating error types and recursive enumerations
- Extending concrete types
- Referencing selectors and key paths
- Working with protocol-oriented programming
- Defining class-only protocols and optional protocols
- Using option sets, type checking, and casting operators