Singletons In Swift - ios

The first time I learned how to Implement Singleton Pattern in Swift is in this Book Pro Design Patterns in Swift.
The way I started implementing the Singleton Pattern is in the example below:
class Singleton {
class var sharedInstance: Singleton {
struct Wrapper {
static let singleton = Singleton()
}
return Wrapper.singleton
}
private init() {
}
}
But then I found this implementation while reading about Cocoa Design Patterns
class Singleton {
static let sharedInstance = Singleton()
private init() {
}
}
So my question is, what's the difference between the two implementations ?

Back in Swift 1 days, static let wasn't implemented yet. The workaround was to create a wrapper struct. With Swift 2, this is not needed anymore.

Related

Static function encapsulation in Swift by passing Protocols.Type better than OO encapsulation and just as testable?

Given that I have a function that does not need to share and store state; should I use a static class/struct/enum to hold the function? I have read in many places that it is a bad design to use static functions to hold code, as static function do not adhere to the SOLID principles and are considered procedural code. Testability seems to be there as I can isolate the parent class with the injected static Enums by injecting mock static enums.
E.g. I can encapsulate and have polymorphism by using protocols for static functions:
Static Protocol Approach
enum StaticEnum: TestProtocol {
static func staticMethod() {
print("hello")
}
}
enum StaticEnum2: TestProtocol {
static func staticMethod() {
print("hello2")
}
}
protocol TestProtocol {
static func staticMethod()
}
class TestClass {
let staticTypes: [TestProtocol.Type]
init (staticTypes: [TestProtocol.Type]) {
self.staticTypes = staticTypes
}
}
class TestFactory {
func makeTestClass() -> TestClass {
return TestClass(staticTypes: [StaticEnum.self, StaticEnum2.self])
}
}
vs
Object Oriented Approach
class InstanceClass: TestProtocol {
func instanceMethod() {
print("hello")
}
}
class InstanceClass2: TestProtocol {
func instanceMethod() {
print("hello2")
}
}
protocol TestProtocol {
func instanceMethod()
}
class TestClass {
let instances: [TestProtocol]
init (instances: [TestProtocol]) {
self.instances = instances
}
}
class TestFactory {
func makeTestClass() -> TestClass {
return TestClass(instances: [InstanceClass(), InstanceClass2()])
}
}
The static version still allows for protocol polymorphism as you can have multiple enums adhere to the static protocols. Furthermore no initialisation is needed after the first dispatch call to create the static function. Is there any drawback in using the Static Protocol approach?
Why static methods can violate SOLID
I have read in many places that it is a bad design to use static functions to hold code, as static function do not adhere to the SOLID principles and are considered procedural code.
I suspect you've read about this in the context of other languages, such as Java, which I'll use as a concrete example for simplicity.
Indeed, this is true for Java. But rather than a hand-wavy quote about why static is the boogeyman, it's good to understand the precise details.
In Java, static methods are truly static. They're really no different than a global function that just happens to be namespaced to a class.
As such, it violated the dependency inversion principle (the "D" in SOLID). Any usage of a static method in Java is a case where the calling code is relying on a concretion (that particular implementation of the method) and not an abstraction (an interface that describes that method), making polymorphism impossible. Essentially there's no way to substitute one implementation for another.
... but not in Swift.
This is just not the case in Swift.
In Swift, when a type conforms to a protocol, instances of that type are guaranteed to meet the protocols requirements for instance methods, properties and subscripts, just like Java.
But as you've discovered, when a Swift type conforms to a protocol, the type itself is guaranteed to meet the protocol requirements for static methods, static properties, static subscripts and initializers.
This goes a step beyond what Java's interfaces can express.
I like to visualize it by thinking of each Swift protocol as acting as if it were (up to) two conventional Java interfaces in one.
When you have:
protocol MyProtocol {
static func myStaticMethod() {}
func myInstanceMethod() {}
}
struct MyImplementation: MyProtocol {
static func myStaticMethod() {}
func myInstanceMethod() {}
}
It behaves as if you had (psuedo-code):
interface MyProtocol_MetaHalf {
static func myStaticMethod() {}
}
interface MyProtocol_InstancedHalf {
func myInstanceMethod() {}
}
struct MyImplementation.Type: MyProtocol_MetaHalf {
static func myStaticMethod() {}
}
struct MyImplementation: MyProtocol_InstancedHalf {
func myInstanceMethod() {}
}
You might recognize this as being eerily similar to the way Java interfaces are often used. You'd often have a pair, interface Foo, and interface FooFactory. I argue that the prevalence of "Factory" classes in Java stems from their interfaces' inability to express static requirements, thus what could have been a static method has to be instead split off into an instance method on a new class.
As you've also seen, Swift's static methods can satisfy protocol requirements and they can be polymorphically called. Example:
protocol MyProtocol {
static func staticMethod()
}
struct Imp1: MyProtocol {
static func staticMethod() { print("Imp1") }
}
struct Imp2: MyProtocol {
static func staticMethod() { print("Imp1") }
}
let someImplementation: MyProtocol.Type = Imp1.self
// A polymorphic call to a static method
someImplementation.staticMethod()
Thus, you can see that the testability issue with Java interfaces doesn't translate to Swift's interfaces. You can easily implement a new mock type that conforms to a protocol with a static requirement, and provide a mock implementation to the static method.
All that is to say: What you proposed is possible (well clearly, you provided a working demonstration). But it begs the question: why would you do it?
Why use metatypes when types will do?
Having a type system that supports both types (which describe the methods of their instances, the objects) and metatypes (which describes the methods of their instances, the types) can be useful for expressing ideas like "I have a widget, and it's paired with a thing that makes widgets, here's how the two go together into one protocol/class/struct."
But what you've done is essentially ... dial up the "meta level" by one. In your example, you use types instead of objects, and metatypes instead of types. But fundamentally, you haven't achieved anything that can't already be expressed more easily/clear using the typical pairing of objects + types.
Here's how I would express what you wrote:
struct Implementation1: TestProtocol {
func instanceMethod() {
print("hello")
}
}
struct Implementation2: TestProtocol {
func instanceMethod() {
print("hello2")
}
}
protocol TestProtocol {
func instanceMethod()
}
class TestClass {
let implementations: [TestProtocol]
init(implementations: [TestProtocol]) {
self.implementations = implementations
}
}
class TestFactory {
func makeTestClass() -> TestClass {
return TestClass(implementations: [Implementation1(), Implementation2()])
}
}
Given that I have a function that does not need to share and store state
They might not need that today, but maybe they will need it in the future. Or maybe not. For now, I just modelled the implementations using empty structs.
This is probably a good time to emphasize there's a difference between "I only need one object of this", vs "I'm adamant I only ever want exactly one object of this".
That might sound silly/obvious, but you'd be surprised how frequently post here asking about how they can be two instances of a singleton :)
If you're totally adamant that you'll never need state, then perhaps you enforce the one-objectness constraint with a singleton:
struct Implementation1: TestProtocol {
public static var shared: Self { Self() }
private init() {}
func instanceMethod() {
print("hello")
}
}

Recreate a singleton

I've come to the unfortunate point where I will need to recreate a singleton.
It looks like this
class Myplayer: AVPlayer {
static let sharedInstance: Myplayer = {
let instance = Myplayer()
return instance
}()
As you can see from this, the reason for this is that AVPlayer can sometimes come into a failed state (.status == .failed) and the documentation specifically mentions that the instance itself will need to be recreated in order to work any further.
I have wound up my app with this singleton pattern and have a few months of live traction with it so changing this to a non-singleton pattern would likely take too much work at this point.
So my question is, how can I recreate this singleton in a pretty way?
I use this pattern whenever I need a singleton that is resettable during (for example) unit tests:
class MyManager {
private static var _sharedInstance: MyManager? = nil
static var sharedInstance: MyManager {
if _sharedInstance == nil {
_sharedInstance = MyManager()
}
return _sharedInstance!
}
static func resetSharedInstance() {
_sharedInstance = nil
}
}
You're on the right track. The key is to create a computed property that checks whether the status of the AVPlayer is .failed, and if so, recreates the instance. A second private static let contains a reference to your singleton and gets returned after the check:
import AVKit
class MyPlayer {
private static var avPlayer = AVPlayer()
private static let _sharedInstance = MyPlayer()
public static var sharedInstance: MyPlayer {
if self.avPlayer.status == .failed {
self.avPlayer = AVPlayer()
}
return self._sharedInstance
}
private init () {}
}
There is no need to recreate the singleton.
You can have a public / internal sharedInstance as a computed property which shares the object from a private _sharedInstance. This way, you can not assign a new instance from outside the class. Also add a static function that recreates the instance by assigning the private _sharedInstance a new Myplayer object.
class Myplayer: AVPlayer {
private static var _sharedInstance = Myplayer()
static var sharedInstance: Myplayer {
return Myplayer._sharedInstance
}
static func recreateInstance() {
Myplayer._sharedInstance = Myplayer()
}
}
As posted in comment, you should never recreate a singltone!
By definition:
In software engineering, the singleton pattern is a software design
pattern that restricts the instantiation of a class to one "single"
instance
Maybe it's a bad news for you, but if AVPlayer isn't designed as a singleton, then you will never be sure, that there is only one instance of a class at the moment. So you or somebody else can create at another place another instance of AVPlayer.
Can recreation destroy a singleton pattern? If programming language does support references to the objects, then definitely YES! (At this point I have to say, that I'm not from ios/swift world ;) )
Just consider such scenario: You have a singleton object and somewhere in code there is a variable SomeVariable_A_OfTypeSingleton, let's say static, which points to the singleton object. Then at some point you do recreate a singleton, so that singleton access method does return new object, BUT the variable SomeVariable_A_OfTypeSingleton still have an old reference to the old object.
So you will have two instances of a class and it will not be a singleton anymore.
The only way I see is to reset the state of singleton(that is probably not possible in your case).

Ios swift class without instantiate

How do you (if possible) create a class that anything that references it gets the same object?
So, if I had a LoginClass
and I dont want to create a new instance in each file but rather be able to just do
LoginClass.userID
in any file without first creating an instance of it?
It possible. Use singleton:
Stackoverflow question
Tutorial by Ray Wenderlich
You are looking for a Singleton
This is the code
class Login {
static let sharedInstance = Login()
var userID: String?
private init() {}
}
This is how you retrieve the same instance
Login.sharedInstance
And this is how you use it
Login.sharedInstance.userID = "123"
In a different point of your code...
print(Login.sharedInstance.userID) // 123
Creating one instance per application life cycle means you want to implement Singleton pattern. You can implement singleton like this
class LoginManager {
static let sharedInstance = LoginManager()
var userId:String?
var name:String?
}
And now you can use this like
LoginManager.sharedInstance.userId

iOS: Subclass singleton in swift

I have a framework where I have a singleton class, let's say Singleton. This class is used by other classes in the framework.
In the app project I want to subclass this singleton class, e.g. AppSingleton: Singleton. Is it possible? What is the right solution?
I provide a solution but it may be a little hacky.
Class A {
open class var shared: A {
return A.privateShared
}
private static let privateShared = A()
}
Class B {
open class var shared: B {
return A.privateShared
}
private static let privateShared = B()
}
I must clarify, this ways isn't perfect since it actually create 2 instance! So, it will technically not a singleton any more.
However, you can override the class B's property or method to call A.shared method or property instead. You must know what you are doing and consider use the other way to fix the problem you want to solve.

How to use multiple protocols in Swift with same protocol variables?

In swift I'm implementing two protocols, GADCustomEventInterstitial and GADCustomEventBanner.
Both of these protocols require a property called delegate. delegate is a different type in each protocol, and thus a conflict arises.
class ChartBoostAdapter : NSObject, GADCustomEventInterstitial, GADCustomEventBanner, ChartboostDelegate{
var delegate:GADCustomEventInterstitialDelegate?; // Name conflict
var delegate:GADCustomEventBannerDelegate?; // Name conflict
override init(){
}
...
}
They are libraries/frameworks it's not my definition
Then obviously you cannot make the same class adopt both protocols. But you don't really need to. Just separate this functionality into two different classes, as is evidently intended by the designer of these protocols. You are supposed to have one class that adopts GADCustomEventInterstitial and has its delegate, and another class that adopts GADCustomEventBanner and has its delegate. What reason do you have for trying to force these to be one and the same class? As in all things where you are using a framework, don't fight the framework, obey it.
It is actually possible, I just encountered same situation. I had two different but kind of related protocols. In some cases I needed both to be implemented by delegate and in other cases only one and I didn't want to have two properties eg... delegate1, delegate2.
What you need to do is create another combined protocol that inherits from both protocols:
protocol ChartBoostAdapterDelegate: GADCustomEventInterstitialDelegate, GADCustomEventBannerDelegate { }
class ChartBoostAdapter : NSObject, GADCustomEventInterstitial, GADCustomEventBanner, ChartboostDelegate {
weak var delegate: ChartBoostAdapterDelegate?
override init(){
}
...
}
The simple answer is that you can't.
Maybe one protocol depends on another, in which case you would use the dependent protocol for the type of your delegate.
Note that this can be solved using Mixins (possible since Swift 2.0) if you are in a Swift-only environment. It just cannot be solved as long as you need to have the code bridged to Obj-C, as this problem is unsolvable in Obj-C. Yet that can usually be solved by a wrapper class, which I will show later on.
Let's break this down to a minimalist example:
import Foundation
#objc
protocol ProtoA {
var identifier: String { get }
}
#objc
protocol ProtoB {
var identifier: UUID { get }
}
#objc
class ClassA: NSObject, ProtoA, ProtoB {
let identifier = "ID1"
let identifier = UUID()
}
The code above will fail as no two properties can have the same name. If I only declare identifier once and make it a String, compiler will complain that ClassA does not conform to ProtoB and vice verse.
But here is Swift-only code that actually does work:
import Foundation
protocol ProtoA {
var identifier: String { get }
}
protocol ProtoB {
var identifier: UUID { get }
}
class ClassA {
let stringIdentifier = "ID1"
let uuidIdentifier = UUID()
}
extension ProtoA where Self: ClassA {
var identifier: String {
return self.stringIdentifier
}
}
extension ProtoB where Self: ClassA {
var identifier: UUID {
return self.uuidIdentifier
}
}
extension ClassA: ProtoA, ProtoB { }
Of course, you cannot do that:
let test = ClassA()
print(test.identifier)
The compiler will say ambigous use of 'identifier', as it has no idea which identifier you want to access but you can do this:
let test = ClassA()
print((test as ProtoA).identifier)
print((test as ProtoB).identifier)
and the output will be
ID1
C3F7A09B-15C2-4FEE-9AFF-0425DF66B12A
as expected.
Now to expose a ClassA instance to Obj-C, you need to wrap it:
class ClassB: NSObject {
var stringIdentifier: String { return self.wrapped.stringIdentifier }
var uuidIdentifier: UUID { return self.wrapped.uuidIdentifier }
private let wrapped: ClassA
init ( _ wrapped: ClassA )
{
self.wrapped = wrapped
}
}
extension ClassA {
var asObjCObject: ClassB { return ClassB(self) }
}
If you put it directly into the class declaration of ClassA, you could even make it a stored property, that way you don't have to recreate it ever again but that complicates everything as then ClassB may only hold a weak reference to the wrapped object, otherwise you create a retain cycle and neither of both objects will ever be freed. It's better to cache it somewhere in your Obj-C code.
And to solve your issue, one would use a similar wrapper approach by building a master class and this master class hands out two wrapper class, one conforming to GADCustomEventInterstitial and one conforming to GADCustomEventBanner but these would not have any internal state or logic, they both use the master class as storage backend and pass on all requests to this class that implements all required logic.

Resources