Difference Between Static Function and Singleton Class in Swift

Difference between static function and singleton class in swift

Sure this sounds confusing and can be debated. However, from the best practices i can put some suggestions.

Singleton is usually used to create a resource intensive and one timer initialisation for instance: a database connector, login handler and such.

Utility class are classes that only have static functions and variables. It should not deal with async task and expensive resource handling like opening a database connector.

In your case, if the utility is doing some resource intensive process its better to wrap in a singleton. If not, then Static functions in a class is better in my opinion. This is so also because, Swift will dispatch all static functions in a class using static dispatch. Whereas this cannot be true in Singleton although Swift likes to optimizes.

Static Dispatch are 4 times faster than Dynamic Dispatch as far as Objective-C runtime is used. This is true for swift too. However, it only takes 4 nano seconds to dispatch Dynamiclly.

I hope this makes you clear.

Swift singleton vs. static properties/methods

To me, a simpler alternative would be to convert all properties and methods to static, and drop the sharedInstance property.

These do not do the same thing. The recommended approach is not actually a singleton at all. It's just a well-known instance. The concept of the Singleton pattern is that there must only be one instance. The concert of the shared instance pattern is that there can be more than one instance, but there is one that you probably want, and you would like easy access to it.

The advantage of shared instances is that they are not magical. They're just instances. That means that they can be handed around as values. They can be replaced with other instances that may be configured differently. They are easier to test (because they can be passed into functions).

True singletons are a very rigid pattern that should only be used when it is absolutely necessary that no other instance exist, usually because they interact with some external unique resource in a way that would create conflicts if there were multiples (this is pretty rare). Even in this case, in Swift, you should generally just make init private to prevent additional instances being created.

If you look around Cocoa, you'll find that shared instances are extremely common for things that would be Singletons in other frameworks, and this has been very powerful. For instance, there is a well known NotificationCenter called default, and it's probably the only one you've ever used. But it's completely valid to create a private NotificationCenter that's independent (I've actually done this in production code).

The fact that UIDevice.current is how you access the device, rather than static methods, leaves open the possibility of new APIs that can handle multiple devices (it also helps with unit testing). In the earliest versions of iOS, the only UIScreen was .main, and it might have made sense to make it a singleton. But because Apple didn't, when mirroring was added in 4.3, it was simple to talk about the second screen (UIScreen.mirrored). You should generally be very slow to assume that there can only be one of something.

Patterns: Singletons vs. Static vars and methods approach

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!

Difference between static class and singleton pattern?

What makes you say that either a singleton or a static method isn't thread-safe? Usually both should be implemented to be thread-safe.

The big difference between a singleton and a bunch of static methods is that singletons can implement interfaces (or derive from useful base classes, although that's less common, in my experience), so you can pass around the singleton as if it were "just another" implementation.

Can you explain me the difference static and class in swift?

The difference between a function defined as static func and another one defined as class func is that static is for functions of structures and enumerations, and class is mainly for functions of protocols and classes.

Class functions can also be overridden by subclasses. For example:

class Animal{
class func generateAnimalSound(){
print("Some Animal Sound")
}
static func isAnimal() -> Bool{
return true
}
}

class Cat: Animal{
override class func generateAnimalSound(){
print("Meow!")
}
}

var someAnimal = Animal.generateAnimalSound() // prints "Some Animal Sound"
var cat = Cat.generateAnimalSound() // prints "Meow!"

However, if you try to override the static member function isAnimal(), this will result in an error:

Cannot override static method

That's obviously because static methods cannot be overridden by subclasses. You should read the documentation provided both by Apple and other StackOverflow related questions:

  • What is the difference between static func and class func in Swift?
  • static vs class as class variable/method (Swift)

  • The Swift Programming Language (Swift 3.1) - Methods

Static vs class functions/variables in Swift classes?

static and class both associate a method with a class, rather than an instance of a class. The difference is that subclasses can override class methods; they cannot override static methods.

class properties will theoretically function in the same way (subclasses can override them), but they're not possible in Swift yet.

Singleton VS static(class) variables

tl;dr

Option 1 (class or struct) when you store mutable state because you need other instances.

Option 2 (scoped global variables) when you want to store static variables because it's faster and uses less memory.

Singleton Class (or struct) with variables

Global state is generally considered a "bad thing". It's hard to think about, causes problems but is sometimes unavoidable.

  • Create a class if you ever want to have multiple SomeManager instances.
  • A singleton can be good default instance but there may be edge cases where you want to have separate behavior (testing).
  • Dependency Injection... is big topic that is relevant if SomeManager is storing global state.

Static Variable

  • Always use when the someVariable is a constant.
  • Does not require extra storage for static var sharedManager = SomeManager(); you use only the memory which you actually need.
  • Slightly faster because you do not need to load sharedManager into memory then access it's member someVariable. You straight up access someVariable.

Bonus Tip:

In Option 2 you can create SomeManager even though it doesn't do anything. You can prevent this by turning SomeManager into an enum with no cases.

enum SomeManager {
static var someVariable: String?
}

You can still do this:

SomeManager.someVariable

but you can't do this

let manager = SomeManger()


Related Topics



Leave a reply



Submit