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.
Related
I'm making Tetris. What is the best solution for shared code amongst the pieces? A class, protocol, or something else?
Tetrimino template capabilities:
func moveDown()
func rotateRight() // based on data table
func rotateLeft() // based on data table
Each type of piece can rotate and move, but the way it rotates is determined by unique data tables. The data tables are the same between all instances of that piece (e.g. all long pieces rotate in the same way), and there is mainly shared functionality upon initialization.
It would make sense to use a protocol with a static variable for the data tables, and a default constructor that is run by conforming classes before running their unique code.
However, with a protocol, the static variables cannot be overridden, nor can a base initializer be provided that conforming classes can add onto. But if I use a class to get around these problems, then Tetrimino instances can be made, when it should just be a template.
What's the best design pattern for this?
Using a protocol with default implementations as your abstraction layer can work for your requirements.
You can declare the dataTable as a static requirement and then from conforming classes, you can make the variable a class variable in case it's computed and you want it to be overridable from subclasses or if it's a stored property, then subclasses can change its value even when it's static (stored properties need to be static anyways).
As for sharing common initialisation code, you can add a static function with a default implementation to your protocol, then call that static function from the init of conforming types.
protocol TetrisPiece {
static var dataTable: [String] { get }
/// Method to be run when creating a new piece
static func setup()
}
extension TetrisPiece {
static func setup() {
print("Doing common stuff")
}
}
class SquarePiece: TetrisPiece {
static var dataTable: [String] = []
init() {
Self.setup()
// Do the custom init here
}
}
TLDR: Using many Swift protocols in a large project is great for testing and SOLID coding, but I’m getting function clutter and invalid redeclaration clashes. What’s the best practice to avoid these problems in Swift while making heavy use of protocols?
Concretely, I want to use protocols to separate responsibilities from view classes such that they don’t need to know anything about the data models used to “decorate” them. But this is creating a lot of functions for my data model classes that are exposed throughout the app, and that are starting to clash with other protocols.
As an example, let’s say I want to set up my custom tableview cell from a certain data model in my project. Let’s call it MyDataModel. I create a decorating protocol like so:
protocol MyCellDecorator {
var headingText: String?
var descriptionText: String?
}
And then my cell is like
class MyCell: UITableViewCell {
#IBOutlet weak var headingLabel: UILabel!
#IBOutlet weak var descriptionLabel: UILabel!
func setup(fromDecorator decorator: MyCellDecorator) {
headingLabel.text = decorator.headingText
descriptionLabel.text = decorator.descriptionText
}
}
Now all I need to do is provide an extension from my data model class implementing MyCellDecorator, providing headingText and descriptionText, and I can plug my data model object into setup(fromDecorator:).
extension MyDataClass: MyCellDecorator {
var headingText: String {
return “Some Heading“
}
var descriptionText: String {
return “Some Description“
}
}
This makes the cell easy to test; it clearly separates responsibilities, MyCell and the UIViewController driving it now need to know nothing about MyDataModel..
BUT now MyDataModel has two extra properties, headingText, and descriptionText - available everywhere. But MyDataModel already extends 10 other decorator protocols for specific UI throughout my project, and it so happens that another protocol already defines headingText, so I get the compilation error “invalid redeclaration of ‘headingText’”.
With all of this headache, I decide to quit, go ahead and just pass MyDataModel into MyCell, it all compiles but I lose all the aforementioned advantages.
What are good ways, in such a big project as this, to score those sweet sweet protocol wins, without cluttering up my class’s function tables and having redeclaration clashes between different extensions?
I agree with where Andrey is going, but I believe it's even simpler. You just need decorator types, and the way you've described them, they should be able to be simple structs, with no inherent need for protocols.
struct MyCellDecorator {
let headingText: String
let descriptionText: String
}
(I've made these non-optional, and I strongly recommend that unless you have a UI distinction between "empty string" and "none.")
Extensions work almost exactly as you've done before:
extension MyDataClass {
func makeMyCellDecorator() -> MyCellDecorator {
return MyCellDecorator(headingText: "Some Heading",
description: "Some Description")
}
}
In some cases, you may find that model objects have very consistent ways that they generate a decorator. That's a place where protocols will allow you to extract code such as:
protocol MyCellDecoratorConvertible {
var headingText: String { get }
var descriptionText: String { get }
}
extension MyCellDecoratorConvertible {
func makeMyCellDecorator() -> MyCellDecorator {
return MyCellDecorator(headingText: headingText,
description: description)
}
}
This example captures the case where the cell happens to have exactly the right names already. Then you just have to add MyCellDecoratorConvertible and the property comes for free.
The key point to all of this is that rather than have model.headingText you'll have model.makeMyCellDecorator().headingText, which will address your explosion of properties.
Note this will generate a new Decorator every time you access it, which is why I'm using a make (factory) naming convention. There are other approaches you might consider, such as an AnyMyCellDecorator type eraser (but I'd start simple; these are likely very small types and copying them is not expensive).
You can split the UI into modules and use internal extensions. Those will not appear in other modules, which will prevent myCellDecorator from showing up everywhere. If more convenient, you can put the myCellDecorator extensions in the same file with MyCell and mark them private.
Since this is a large, existing code-base, I highly recommend allowing any existing code duplication to drive your design. There is no one pattern that is ideal for all systems. It's not even necessary to have every decorator follow the exact same pattern (in some cases it may make more sense to use a protocol; in others a struct; in others you might want both). You can create a pattern "language" without boxing yourself into a world where you're creating extra protocols just because "that's the pattern."
But MyDataModel already extends 10 other decorator protocols for specific UI throughout my project, and it so happens that another protocol already defines headingText, so I get the compilation error “invalid redeclaration of ‘headingText’”.
I think this is the main pitfall here, that you use single model to provide data for different parts of the application. If we are talking about the MVC pattern, then the single model should only provide data for corresponding controller. I think in this case there will be much less protocol adoptions in the model.
On other hand you can try to split functionality inside of the model:
For instance, if we have
protocol CellDecorator {
var headingText: String?
var descriptionText: String?
init(withSomeData data: ...) {}
}
we could create something like this
class MyCellDecorator: CellDecorator {
var headingText: String?
var descriptionText: String?
}
class MyDataClass {
lazy var cellDecorator: CellDecorator = {
return CellDecorator(withSomeData: ...)
}
}
One struct-based way I've played with is this:
Instead of extending MyDataClass, I create a simple struct (which can be fileprivate to the view controller class, or not) that looks like:
struct MyDataClassCellDecorator: MyCellDecorator {
var headingText: String? {
return "Some heading with \(data.someText)"
}
var descriptionText: String? {
return data.someOtherText
}
let data: MyDataClass
}
This way MyCell can still use the protocol to decorate itself, MyDataClass doesn't need any extension at all, and in whatever access scope I want it I get a struct that does the decorating logic for MyDataClass + MyCellDecorator.
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...
In the app that I'm currently working on, I try to take advantage of the new protocol extension feature in Swift. The idea is that I have a lot of classes implementing the same protocol. Since all these classes should have the same computed properties, and since the properties should behave identically in de different classes, I thought it would be nice to add the functionality only once.
My code is structured as the following example
protocol SomeProtocol { ... }
// There could potentially be unlimited different versions of "SomeClass" that implements "SomeProtocol"
class SomeClass : SomeProtocol { ... }
extension SomeProtocol {
var computedProperty1: Type? {
get { getData(SOME_ENUM) }
set { validateAndSave(newValue, atKey: SOME_ENUM) }
}
var computedProperty2: Type? {
get { getData(SOME_OTHER_ENUM) }
set { validateAndSave(newValue, atKey: SOME_OTEHR_ENUM) }
}
...
func getData(atKey: ENUM_TYPE) -> Type? {
[NEED SOME WAY TO GET THE SAVED DATA AND RETURN IT]
}
func validateAndSave(value: Type?, atKey: ENUM_TYPE) {
[NEED SOME WAY TO SAVE DATA FOR LATER RETURNING]
}
}
// The properties needs to be visible to the client code like this:
class ClientCode {
let someClassObject: SomeProtocol = SomeClass()
someClassObject.computedProperty1 = Type()
print(someClassObject.computedProperty1)
}
(The code above shows signs of storing the data in different dictionaries, which was my first thought)
The problem is that an extension does not support stored properties. But where/how do I store the data submitted to the computed properties then?
I can think of 2 different solutions, but none of them good..
I could transform the extension into a class that implements SomeProtocol instead, and then make SomeClass a subclass of it. That would allow me to save the data in stored properties. But it would also require me to implement all the methods the protocol requires in the new class - and that makes absolutely no sense, since it's the different versions of SomeClass that should provide different functionality..
I could just drop the entire extension idea, and move all the properties into SomeProtocol. But that would require me to implement all the computed properties in all the different versions of SomeClass with identical functionality, and the whole point of my extension idea was to avoid writing the same implementation for the same properties over and over again..
Is there some completely easy logical solution that I have overlooked?
... or a nice way to save data in a protocol extension that I do not know about?
... or another way of obtaining the desired functionality?
... or should I just suck it up and use one of my not-so-pretty solutions?
Assuming I understand the question correctly to work around the fact that protocol extensions don't support stored properties you could extend NSObject and use the objective C runtime to store your properties.
import ObjectiveC
private var AssociationKey: UInt8 = 0
class YourStoredObject {
// Whatever object your are persisting
}
extension NSObject {
var yourStoredObject: (YourStoredObject)! {
get {
return objc_getAssociatedObject(self, &AssociationKey) as? YourStoredObject
}
set(newValue) {
objc_setAssociatedObject(self, &AssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
}
protocol YourProtocol {
var yourStoredObject: YourStoredObject! { get set }
}
extension YourProtocol {
func customYourStoredObjectGetter() -> YourStoredObject {
return yourStoredObject
}
}
extension UILabel : YourProtocol {
func myExtendedFunc() {
// Get (and print) your object directly
print(yourStoredObject)
// Get your object through a protocol custom getter
print(customYourStoredObjectGetter())
// Set your object
yourStoredObject = YourStoredObject()
}
}
I'm not saying this is the best solution but this is the only solution I can think of. I'm also looking for nicer Swift alternatives but still have not found any.
Protocol extension? Why?
Sometimes we get so hung up on an idea that we ignore a practical solution staring right at our face.
1. Do you have set of computed properties? No, you want stored properties.
Since all these classes should have the same computed properties, and
since the properties should behave identically in de different
classes...
... but later
The problem is that an extension does not support stored properties.
But where/how do I store the data submitted to the computed properties
then?
2. Assuming that it is a set of stored properties that you want, you practically provided the solution yourself! Made one change that will make sense now.
I could transform the extension into a class that implements
SomeProtocol instead, and then make SomeClass a subclass of it. That
would allow me to save the data in stored properties.
You extend the class whenever you want to and then confirm its subclasses to SomeProtocol to get the features. This is cleaner.
On a side note, Swift's protocols not being able to store properties is by design. Protocols do not have existence in their own right and it doesn't make sense to add stored properties in them.
I am trying out to create a singleton in SWIFT and this is what I have done so far
class Global {
class var sharedInstance:Global {
struct singleton {
static let instance:Global = Global()
}
return singleton.instance
}
}
var a = Global.sharedInstance
var b = Global()
if a === b {
println("Pointing to Same Instance")
}
else {
println("Pointing to different instance")
}
I have used computed type property to create a singleton (learnt that from another stackoverflow question).As of now the output is "Pointing to different instance".
What I am looking for is "a" and "b" in above example points to different instance of GLOBAL class and this breaks the point of singleton. How to make "a" and "b" in above example to point to the same instance of the class.
Thank you
This pattern does not guarantee there will only ever be one instance of the Global class. It just allows for anyone to access a single common instance of Global via its sharedinstance property.
So Global() declares a new instance of the Global class. But Global.sharedinstance does not create a new instance of Global, just fetches a pre-created one (that is created the first time anyone accesses it).
(If you alter your declaration of b to read var b = Global.sharedinstance you’ll see it confirms that a and b are pointing to the same instance.)
If you want to ban the creation of further instances of Global, make its init private:
private init() { }
But bear in mind you’ll still be able to create other Globals from within the file in which it’s declared, so if you’re doing the above in a playground or single-file test project, you won’t see any effect.
Class instance once in App life cycle.
class AccountManager {
static var sharedInstance = AccountManager()
var userInfo = (ID:"Arjun",Password:"123")
private init(){
print("allocate AccountManager")
}
}
here we set Private because :
Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.
also set static property of sharedInstance
because if you need to access class property without instance of class you must have to declare "Static".