In Swift, What is the difference between a Singleton and the static version of a class? - swift

I have not found myself using a singleton in a while because I get all the functionality of one from the static class. Are there any differences between the two that I should be aware of?
Singleton Example:
class SomeManager {
static let sharedInstance = SomeManager()
var user: User!
init(user: User) {
self.user = user
}
}
With usage:
SomeManager.sharedInstance.user
Static Class Example:
class SomeManager {
static var user: User!
init(user: User) {
SomeManager.user = user
}
}
With usage:
SomeManager.user
I know the obvious difference is that one is an entire class being made static, and the other is declaring specific parts (that are desired to be from a single instance) static. Is there any reason to use one over the other.
I have one setup for my Network right now where I have a singleton class of network calls that are accessed through a bunch of static methods in a class that does nothing but contain the Network singleton and its static methods. I find this to have the appropriate scope for my scenario, but have not done enough research to guarantee the quality of the method.
Example:
class NetworkCalls {
static let network = Network()
static func getToken(completion: () -> Void) {
network.apiGetToken() {
completion()
}
}
}
With usage:
NetworkCalls.getToken() {
print("Network Call Completed")
}
It works fine, so I am only looking for matters of efficiency, things to think about, and differences between this and alternative methods. Any tips/advice would be highly appreciated!

I may be wrong, but the idea of a singleton is to get a unique single class avaliable for all the application, which is only initialized once in a life time (most cases) and used mostly for state validations during the lifetime of your app.
A static class is more general use kind of class.
Althought you can do the same with a static class...

Related

Hiding inner class in swift

I'm trying to hide a inner class so the caller is not aware of it. If the caller want, they can get an instance of the inner class by using a public method. But the caller should not be able to directly get the inner class.
Example to show what I want:
class A {
static func getSettings() -> Settings {
return Settings()
}
class Settings {
func turnOnSomeThing() {
}
}
}
class test {
func testFunc() {
A.getSettings().turnOnSomeThing() // correct way of calling
A.Settings().turnOnSomeThing() // should not be possible
}
}
Is this possbile in Swift?
Why do both calls work in the test caller?
Both currently work because:
The first case, A.getSettings()... is a classic getter that returns an object. I'm just puzzled with the fact that a new Settings is constructed each time, but this is perfectly legit.
The second case, A.Settings().... invokes the constructor of Settings to create an anonymous object, and invokes some methods on it. It's ok, because the inner class is public, but it's weird.
Can you make the inner class private?
You could make an inner class private to avoid it being accessed from the outside world:
This would work perfectly well for an private helper class totally invisible to the outside world.
For Settings this is not possible, because getSettings() returns objects of this class to the outside world, and this makes only sense if the outside world knows the class to deal with it.
Exemple:
class A {
static func getSettings() -> Settings { // ERROR if Settings would be private
let helper = Helper() // purely internal use: Helper can be private :-)
helper.demo()
return Settings()
}
class Settings { // making private is not possible (see above)
func turnOnSomeThing() {
print ("On")
}
}
private class Helper { // Cannot be used outside
func demo() {
print ("Demo")
}
}
}
But how to do with Settings?
If you want to return Settings objects to the wild outside world you need to keep that class public. However, if you want to avoid that the outside world misues the inner class and avoid objects to be created from the outside wolrd, you can use access control on the constructor:
class A {
static func getSettings() -> Settings {
...
}
class Settings {
fileprivate init() { /// <=== ACCESS CONTROL internal or fileprivate
}
func turnOnSomeThing() {
...
}
}
}
This prevents the calls of the form A.Settings()..., but only according to swift access control: with internal you can still call the constructor from another file of the same module; with fileprivate the constructor can only be called from within the source file in which you've defined your external class.
This technique of making the constructor inaccessible while keeping the class usable is frequently used for classes which instances shall only be created via a factory.

Shared instance accross inheritage

Say a framework provides customizable services through an open class A, that exposes a shared instance to use as follows:
open class A {
public static let shared = A()
open func aService() {}
}
The regular usage of the service is as follows:
A.shared.aService()
Important note: the shared instance itself is also used from within the class A code or related code in the Framework.
Say you want to customize the service through inheritance, and you still want to keep the use of the shared instanced as follows:
override class B: A {
public override func aService() {
super.aService()
}
}
When you refer to the shared instance, unfortunately, it refers to the class A instance where you would like it refers to the inherited class instance.
B.shared.aService() // Failed!: This actually calls A.shared.aService()
One way to fix it is to make the construct as follows:
class A {
public static var shared = A()
}
Then you are sure before any use of the service within you app, to change the instance as follows:
A.shared = B()
B.shared.aService() // OK! This actually calls B.aService()
Though the whole thing works, I would like to make it automatic and not rely on the initial line that changes the shared instance.
How would you do that?
[CODE FOR PLAYGROUND] that illustrates the goal to achieve and to help you better understand the question
open class A {
public static var shared = A()
open func aService() {
print("\(type(of: self)): service (from A)")
}
}
class B: A {
public override func aService() {
super.aService()
print("\(type(of: self)): service (from B)")
}
}
A.shared = B() // Question : How to remove the need to this line, yet achieving the same functionality (and output)
A.shared.aService()
B.shared.aService()
// The output (which is correct) :
//B: service (from A)
//B: service (from B)
//B: service (from A)
//B: service (from B)
There's a solution, but...
I do, personally, agree with the other comments here. This really doesn't sound like a job for the singleton pattern.
In your current solution, you seem perfectly happy to overwrite the singleton instance mid-execution, which means it's not a singleton. There's only ever supposed to be one instance of a singleton, and if you can continually create and assign a new instance to the shared variable without breaking anything, then it's just not necessary to have this global state across your application.
However, for the record, you can achieve what you want with a struct that composes the static instances of each class, and which can detect the calling context and return the appropriate one each time shared is accessed:
protocol ExampleProtocol {
static var shared: ExampleProtocol { get }
func service()
}
struct ExampleProvider {
private static var a = A()
private static var b = B()
static func instance(type: ExampleProtocol.Type) -> ExampleProtocol {
return type == A.self ? ExampleProvider.a : ExampleProvider.b
}
}
class A: ExampleProtocol {
static var shared: ExampleProtocol {
return ExampleProvider.instance(type: Self.self)
}
func service() {
print("Hello")
}
}
class B: A {
override func service() {
print("Goodbye")
}
}
A.shared.service() // Hello
B.shared.service() // Goodbye
So, yes, you can achieve what you want. But there's a pretty strong case for saying that you shouldn't...

Patterns: Singletons vs. Static vars and methods approach

I am reading a lot about the Singleton Pattern. I am currently using it to store groups of global state in my first app. I am reaching a point where I wonder which approach to implement API client classes and similar with.
Are Structs with static vars and static functions having the same issues?
To illustrate what I mean, I've tried to write the same heavily simplified and exact same(?) scenario twice.
1. A singleton being worked with by a view controller:
struct APIClientSingletonClass {
static let shared = APIClientSingletonClass()
var stateOfSomehting: Bool = true
var stateOfSomehtingMore: Bool = false
var stateNumber: CGFloat = 1234
var stateOfSomehtingComputed: CGFloat {
return stateNumber * 10
}
func convertSomethingToSomethingElse() {
// calling method in self like this:
otherMethod()
}
func otherMethod() {
// doing stuff here
}
}
// Calling APIClient from outside:
class ViewControllerTalkingToSingleton: UIViewController {
var api = APIClientSingletonClass.shared
override func viewDidLoad() {
super.viewDidLoad()
api.convertSomethingToSomethingElse()
api.stateOfSomehting = false
}
}
2. Another approach:
struct APIClientStruct {
static var stateOfSomehting: Bool = true
static var stateOfSomehtingMore: Bool = false
static var stateNumber: CGFloat = 1234
static var stateOfSomehtingComputed: CGFloat {
return stateNumber * 10
}
static func convertSomethingToSomethingElse() {
// calling method in self like this:
APIClientStruct.otherMethod()
}
static func otherMethod() {
// doing stuff here
}
}
// Calling APIClient from outside:
class ViewControllerTalkingToStruct: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
APIClientStruct.convertSomethingToSomethingElse()
APIClientStruct.stateOfSomehting = false
}
}
What do you guys think? Is approach 2 falling into the same traps that seem to make Singletons such a double-edged sword?
Any input is really appreciated!
Best from Berlin
EDIT:
This thread is pretty interesting, but I'm not sure it really relates to my question:
Difference between static class and singleton pattern?
Since there are many perspectives on this topic, let me specify:
Does my approach 2 have the same problem implications with testing and code maintainability?
A class-based singleton is the way to go, provided you accommodate for dependency injection for your tests. The way to do this is to create a single singleton for your app, called, say, DependencyManager. In your AppDelegate (or from other classes if needed), you'd create whatever controllers, network services, realm models, etc you want to hang on your DependencyManager, and then assign them to the DependencyManager. This code would be skipped by your unit tests.
Your unit tests can then access the DependencyManager (and thus instantiate the DependencyManager during first access), and populate it with mock versions of those controllers and services to whatever degree each unit test desires.
Your UIViewControllers, your MVVM view models, etc... can access the DependencyManager as a singleton, and thus get either the real controllers and services, or a mock version of them, depending on if you're running the app or unit tests.
If you're doing MVVM, I also recommend that when a UIViewController is about to create its view model class, that it first checks a special property in the DependencyManager to see if a mockViewModel exists. A single property can serve this purpose, as only one of your UIViewControllers ever would be tested at once. It'd use that property instead of creating a new view model for itself. In this way, you can mock your view models when testing each UIViewController. (There's other tricks involved to being able to prop up a single UIViewController for testing, but I won't cover that here).
Note that all of the above can work very nicely with an app that also wants to use storyboards and/or nibs. People are so down on storyboards because they can't figure out how to do dependency injection of mock services for their view controllers. Well, the above is the solution! Just make sure in your AppDelegate to load the storyboard AFTER setting up the DependencyManager. (Remove the storyboard name from your info.plist, and instantiate it yourself in AppDelegate).
I've written a few shipped apps this way, as well as some sample apps for an SDK, along with the tests. I highly recommend the approach! And be sure to write your unit tests and viewController tests either during or at least immediately after development of each such class, or you'll never get around to them!
What generally makes sinlgetons hard to test is that the singleton objects are typically always accessed directly . Because of this, you don't have a means to substitute the real singleton object (e.g. a data-store that's backed by a database) with a mock object for testing (e.g. a data-store that's backed by an easily-configurable array of predefined test data).
Using static members has the same fundamental issue. When referencing a static member directly, you don't have a means of substituting a mock object in place of the real prod implementation.
The solution to this is quite simple: don't access singleton members directly. What I do is something like this:
// An example of a dependency.
protocol DataAccessLayer {
func getData() -> [Int]
}
// A real implementation of DataAccessLayer, backed by a real production database
class ProdDB: DataAccessLayer {
static let instance = ProdDB()
private init() {}
func getData() -> [Int] {
return [1, 2, 3] // pretend this actually queries a DB
}
}
// A mcok implementation of DataAccessLayer, made for simple testing using mock data, without involving a production database.
class MockDB: DataAccessLayer {
func getData() -> [Int] {
return [1, 2, 3] // The mock *actually* hardcodes this data
}
}
// A protocol that stores all databases and services used throughout your app
protocol ServiceContextProtocol {
var dataAccessLayer: DataAccessLayer { get } // Present via protocol, either real impl or mock can go here
//var fooAPIGateway: FooAPIGateway { get }
//... add all other databases and services here
}
// The real service context, containing real databases and service gateways
class ProdServiceContext: ServiceContextProtocol {
let dataAccessLayer: DataAccessLayer = ProdDB.instance
//var fooAPIGateway: ProdFooAPIGateway { get }
//... add all other prod databases and services here
}
// A mock service context, used in testing, which provides mocked databases and service gatways
class MockServiceContext: ServiceContextProtocol {
let dataAccessLayer: DataAccessLayer = MockDB()
//var fooAPIGateway: MockFooAPIGateway { get }
//... add all other mock databases and services here
}
let debug = false // Set this true when you're running in a test context
// A global variable through which you access all other global state (databases, services, etc.)
let ServiceContext: ServiceContextProtocol = debug ? MockServiceContext() : ProdServiceContext()
// Always reference ServiceContext.dataAccessLayer, ServiceContext.fooAPIGateway, etc.
// and *never* reference ProdDB.instance of MockDB directly.
I would use a Class based Singleton. Just remember the 2 criteria for having a singleton. You want GLOBAL ACCESS and SINGLE INSTANCE in your program. There is a couple problems where struct based singleton would fail. Once you assign a struct to a new variable, Swift makes a complete copy under the hood.
Another useful snip of information can be found using this link.
What's the difference between Struct based and Class based singletons?

Could a Swift Singleton be a class with purely class functions

This feels like the discussion stopped a couple of Swift iterations ago, but I'm curious that in the discussions, it was never suggested (or if it was I never saw it) that a singleton could just be a class with purely class functions, eg -
class MySingleton {
private static var someVar: String?
private static var someOtherVar: SomeType?
class func start() {
// etc...
}
class func doSomething() {
// etc...
}
// etc, etc...
}
Are there any good reasons why we shouldn't do this? I can't think of any.
What do you want to achieve?
In my experience your approach is fine, if
you don't want to create an instance of your class
you don't care, that someone can create an instance of your class (which does not have any benefits, but is still technically possible).
someVar and someOtherVar should contain always the same value for all instances.
Another approach is to have a sharedInstance
class MySingleton {
private(set) static var sharedInstance = MySingleton()
private var someVar: String?
private var someOtherVar: SomeType?
func start() {
// etc...
}
func doSomething() {
// etc...
}
// etc, etc...
}
This gives you more flexibility.
You can call MySingleton.sharedInstance.start() if you want to use the shared instance.
But on the other hand, you can still create your own instance like let customInstance = MySingleton, with its own values for someVar and someOtherVar.
So it really depends on what you want to achieve. If you want to be sure, that no one can create another instance with its own vars, then your approach is safer than my alternative.
In that case, you might even want to consider to make the class final, so no one can create a subclass that behaves differently.
If an object is never instantiated, it's not a singleton. There are no instances of the object, not just a single instance.
There's nothing inherently wrong with doing that, but what's the benefit?
EDIT
It strikes me that the real comparison is between a class that only has class methods and global functions.
In that comparison, the benefit I see is name-spacing. When you create class methods, you have to qualify function calls with the name of the class, so you can say
SomeClass.someMethod()
or
SomeOtherClass.someMethod()
Those are 2 distinct functions and it is obvious that they are distinct functions.
With global functions, you simply say
someMethod()
If at a future date you merge in somebody else's code that also has a global function someMethod() you will get a compiler error about a duplicate function and have to resolve it.

Is this bad or good for performance if I always initialize one type of class in different classes?

world! I have an Actions class, where I hold all actions, animations and sound-plays in my sprite-kit game. So in all my SKNode, SKScene, SKSpriteNode classes I always initialize this Actions class. Is this good for performance? Or I have to initialize this one once, for example in GameViewController and then pass a copy of this class to all other classes, where I need?
As Fogmeister has mentioned in his comment you can use static methods to achieve this. This should also help with performance.
If you check the SKAction documentation you will notice that it uses class vars and methods as well.
In general if you do not need to instantiate a class multiple times, which your case is a perfect example of, than its best to use static/class methods or Singletons.
You can either use a class, struct or enum. I prefer to use enums because you cannot instantiate them by accident or need to add a private initialiser.
// Class
class SKActionHelper {
static var someProperty = ...
static func someMethod() {
...
}
}
// Struct
struct SKActionHelper {
static var someProperty = ...
static func someMethod() {
...
}
}
// Enum
enum SKActionHelper {
static var someProperty = ...
static func someMethod() {
...
}
}
Now you can call those properties or methods anywhere in your project and do not need to instantiate the class each time.
SKActionHelper.someProperty = ...
SKActionHelper.someMethod()
Hope this helps