I'm using a singleton in a Swift 3project I've built.
As part of the project I have registration and login view controllers and I figured I might want registration/login in future projects. So for code reuse I thought about having the registration and login functions in separate .swfit classes and then I'd instantiate these classes in the singleton.
Or just have the registration/login functions as static functions in separate files.
I just wasn't sure if that breaks the idea of a singleton and that all the registration/login functions should be in the singleton.
It's a bit hard to come by practical examples of design patterns in my college degree studies, teachers like data structures, and many other coding topics but not so much about design patterns and how to write better structured code.
In general, you should regard view controllers as not reusable, because they mediate between this particular data and this particular interface (model-view).
But if you can isolate this particular functionality into an independent object, that would make it reusable. What I usually do is make a custom struct and have the view controller own this as a helper object. I don't quite see the point of the putting the struct declaration in a separate file, since it's easy to copy and paste, but you can certainly do that if you like.
(Nor do I see what any of this has to do with Singleton.)
For better learning Design Pattern I recommend the fun and easy reading Head First Design Patterns
Regarding your question about a Singleton pattern in Swift code is always best learned with an example:
final class AccountUtility {
//here is object instantiation to meet the Singleton Design Pattern single instance requirement
static let shared = AccountUtility()
//a private constructor ensures no one can create an instance of this class
private init() {
}
func login() {
}
func register() {
}
}
To use this Singleton Swift class:
AccountUtility.shared.login()
Related
I have a Swift singleton class that maintains app state by storing several arrays. What is the best practices' way to go here? Should we change it, and if we do, then how?
Here is the singleton class:
import Foundation
class FilterModel {
static let sharedInstance = FilterModel()
private init() { }
var muscleExercisesArray = [Int]()
var equipmentExercisesArray = [Int]()
var typeExercisesArray = [Int]()
}
If you're wondering about the basic singleton pattern, a couple of observations:
I might suggest you declare the class to be final, too, to avoid having some future developer subclass it and introduce confusion about to what type sharedInstance refers.
I might also suggest that in Swift 3, the convention is to simplify the name of sharedInstance to just shared. It's not a hard and fast rule, but is the emerging standard.
This implementation is not thread-safe. If you're ok with that, I'd at least include some warning in the comments warning future developers of this concern. Or, obviously, with a little work you could change this to be thread-safe by wrapping this all in some internal synchronization mechanism.
You said:
Singletons are considered a bad approach towards app architecture, so I was wondering what to do instead of it when we need to maintain app state. Somehow I can not find anything online except for DI approach that does not work (or I do not know how) in this case when we need app state to be modified by different files
Yes, singletons are not ideal for model objects for a number of reasons (makes unit testing harder; makes responsibilities unclear, etc.) and there are better patterns (see What's Alternative to Singleton). At the very least, one simple approach is to have app delegate or root view controller instantiate this model object and then only pass this to whatever subsequent controllers need access to it (e.g. in prepareForSegue). This way, it's explicit which objects might be interacting with the model, making responsibilities a little more clear.
I am new to Swift and OOP. For example, I have a class that manages the system-wide configurations.
class system_conf {
init()
getValue1()
getValue2()
...
setValue1()
setValue2()
...
reloadValues()
activateX()
activeteY()
...
}
This class should have only one instance and many other classes will use it. What's the recommended way for this case?
Should I pass around this instance?
Should I consider to use Singleton?
Should I use static functions directly?
Should I create a global instance, so every other class can access it directly?
or?
It seems your class is a configuration class. If you intend to pass it to a bunch of classes, you should wonder if you need to write unit tests for them.
If so, assuming you are either using a singleton or static methods or a global var, take a moment to think about how you would mock this configuration class for each of your tests. It's not easy, is it?
If your class is a kind of mediator, a global var or static methods are fine (or any other alternative you suggested). However, in your case, it would be better to pass your object in any initializer/constructor of each class using it. Then, testing would definitely be easier. Also, passing it via an interface is even better: you can mock it super easily (mock up libraries mostly work with interfaces only).
So there is no unique answer to your question. It is just a matter of compromises and scaling. If your app is small, any of the method you listed above is perfectly fine. However, if you app tends to get bigger, a proxy solution would be better for maintainability and testability.
If you fancy reading, you should glance at this article from Misko Hevery, especially this chapter.
Coming from Objective-C, I am very fond of header files which expose the interface of a piece of code. Swift has always bothered me a bit because even the most organized code still tends to bury the public/private API's among the rest of the code, making you dig for details.
Are there any practices or tricks where I can define the public interface of a class or module external to the implementation? Right now I'm just making comments at the top of the Swift file and it feels arcane.
As far as I know you can not just declare a method in a class and implement it at other places in Swift.
I feel you want that for clarity and organizing your methods into class. To achieve that in Swift I follow some techniques that I would be happy to share with you:
Organize methods in groups based on access i.e. public, private and internal. Public methods on top as you want your client to look at them first, then internal and last private.
You may sub organize related methods together for making it easy to understand, maintain and navigate through.
Some time it is good to break above rules to group public and private method if they are related and has heavy dependancies.
You may group related methods that do a specific task in to extensions. I generally follow this pattern for implementing specific protocol or delegate in a class. This you could do in a separate file as well.
This is not direct answer to your question but I have tried to address the core of it by targeting organization of methods in a class.
So I've been exploring the options here and it looks like you can define an interface using a protocol, and having your class conform to that protocol. Kind of out of the way, but if a public interface is the goal, this achieves that.
// Foo.swift
protocol PublicFoo {
func publiclyExposedMethod(arg:AnyObject) -> AnyObject
var publiclyExposedVariable:AnyObject
}
class Foo : PublicFoo {
var publiclyExposedVariable:AnyObject = // something
func publiclyExposedMethod(arg:AnyObject) -> AnyObject {
// do stuff...
}
}
Looking at:
Using a dispatch_once singleton model in Swift
I see a very generic pattern for creating a shared singleton instance of my class. What I'd like to be able to do is create an extension for "all classes" that implements this sharedInstance method with generics.
I don't see any syntax for doing this; anybody want to take a crack at it?
As others have pointed out, Swift offers a simpler way to create singletons.
As an example: let's say we have a class called Model, and we want to have a single instance, visible throughout our app. All we need to write in the global scope is:
let modelSingleton = Model()
This will create an instance of the Model class, visible everywhere, and that cannot be replaced by another instance (Hmmm, that's pretty much what one would expect from a singleton, isn't it?).
Now, this way of doing would, on the other hand, still allow you to create other Model instances, apart from the singleton. While this departs from the official definition of singletons in other languages, this approach would have the interesting advantage of allowing the creation of other instances for testing purposes (singletons have bad press in the unit testing world :) ).
Swift will soon offer everything needed to create real Singleton<T> classes (it's hard now because class vars aren't allowed yet). But that being said, the approach described above will probably be more than enough for many Swift programmers.
I don't think this is possible.
Even if it was possible to extend Any / AnyObject, every object would share the same implementation of the sharedInstance singleton getter, and therefore the same static instance variable. Thus, instance would get set to an instance of the first class on which sharedInstance was called.
extension Any {
class var sharedInstance:TPScopeManager {
get {
struct Static {
static var instance : TPScopeManager? = nil
}
if !Static.instance {
Static.instance = TPScopeManager()
}
return Static.instance!
}
}
}
...
NSString.sharedInstance() // Returns an NSString
NSArray.sharedInstance() // Returns the same NSString object!
In Swift you can make an extension to NSObject, but you can't extend Any/AnyObject
I have an application that has database connectivity and although there are obviously objects that correspond to data in my database, I find that all my data processing methods could be static as there is no real need for an instance of the object as my classes simply operate on the data and spit something out, no need to store anything outside the method's scope. If I can make a method or class static should I?
Also I use a utility singleton class for common (single instance) "global data". I want to have a good design, but are these frowned upon?
Let me give you an example of what I'm doing. I load some data from my database using a static method to place it into a global varaiable in my Singleton class (a list of a custom object)
So my singleton class has something like
List<MyCustomObject> SomeList
and my static class has
static void LoadData()
foreach(data in database something or other)
singletonClass.SomeList.Add()
So the code above might load in some records from the database into SomeList, where each item in SomeList is of type MyCustomObject, which contains a single record of information.
Is this good implementation? Is this how you would code it?
Then in my presentation layer I would make calls to another static class of methods to get data from the singleton class in to a format required.
It doesn't feel very OOPey. But I can't really think how to do it another way you do it.
Allow me to direct you toward an excellent article on this topic: Singletons are Pathological Liars.
The problem is that the need to call your LoadData() function isn't self-evident. Compare your situation to that described in the article and I think you'll see some parallels.
Statics and singletons are frowned upon somewhat. But only the same way as starting a sentence with “but” — bad when overused, but sometimes it's what works best.
In your example, why have separate classes, one a singleton and one static? A singleton is in many ways equivalent to a class with only static data and methods. If you already have a singleton, I'd say you should add the methods to load the data to it rather than to a separate class. A class with static methods would be more appropriate if, say, you have utility code common to all of your stored data types.
(Also, I wouldn't worry too much about what's OOPey and what's not. Overengineering in the blind service of OOP principles can be a serious problem, speaking as someone who's had to wade through the Eclipse code base …)
Singletons is one but static is another very big one.
OOP or not, static variables have many drawbacks but little coding convenience.
Can't determine exact allocation time, life span
Can't work well in multi-threaded
Future problem to program expansion
...