Singleton and init with parameter
A literal translation of your Objective-C code might be:
private var _asteroidSharedInstance: Asteroid!
class Asteroid {
private var config: ASTConfig?
class func setup(config: ASTConfig) -> Asteroid {
struct Static {
static var onceToken: dispatch_once_t = 0
}
dispatch_once(&Static.onceToken) {
_asteroidSharedInstance = Asteroid(config: config)
}
return _asteroidSharedInstance
}
class var sharedInstance: Asteroid! { // personally, I'd make this `Asteroid`, not `Asteroid!`, but this is up to you
if _asteroidSharedInstance == nil {
println("error: shared called before setup")
}
return _asteroidSharedInstance
}
init(config: ASTConfig) {
self.config = config
}
}
Or, in Swift 1.2, you could eliminate that Static
struct and simplify setup
a bit:
private static var setupOnceToken: dispatch_once_t = 0
class func setup(config: ASTConfig) -> Asteroid {
dispatch_once(&setupOnceToken) {
_asteroidSharedInstance = Asteroid(config: config)
}
return _asteroidSharedInstance
}
This really isn't a singleton. (I suspect you know this, but I mention that for the benefit of future readers). Typically singletons can be instantiated wherever and whenever they're first used. This is a scenario where it's being instantiated and configured in only one particular place and you must take care to do this before you try to use it elsewhere. That's very curious approach. We lose some singleton functionality, but still suffer all of the traditional singleton limitations.
Clearly, if you're ok with that, that's fine. But if you're entertaining alternatives, two jump out at me:
Make this real singleton: You can accomplish this (eliminating the dependency of having to call
setup
before you usesharedInstance
) by moving the instantiation of theASTConfig
inside theinit
method. Then you can retiresetup
and just use your singleton like normal. The resulting implementation is greatly simplified, too. It gets reduced down to something like:class Asteroid {
static let sharedInstance = Asteroid()
private let config: ASTConfig
init() {
self.config = ASTConfig(...)
}
}Clearly, I suspect the devil is in the details of that
ASTConfig
object, but if you can do a proper singleton implementation, as you can see this is much simpler (esp. in Swift 1.2). And the above eliminates thesetup
vssharedInstance
problem. Eliminates the private global. Just simpler all the way around.Having said that, I assume you had compelling reasons to do it the way you did. Perhaps there is some critical reason why you must pass
ASTConfig
object tosetup
method rather than just instantiating it yourself within theinit
of theAsteroid
class.I just felt obliged to point out that a proper singleton would be greatly preferable (both much simpler implementation and eliminates theoretical race conditions).
Abandon singleton pattern entirely: Assuming using a proper singleton, as outlined above, is not possible, the next question is whether you should just abandon any remaining semblance of a singleton, just instantiate a simple
Asteroid
where you are currently callingsetup
, and then rather than relying uponsharedInstance
, just pass it to the objects that really need it.You already have specified that you're going to manually
setup
theAsteroid
up front, so let's formalize that relationship and eliminate many of the structural flaws that singletons introduce (see What's Alternative to Singleton or google "singletons are evil").
Don't get me wrong. I assume that you have compelling reasons to do it the way you have, and if the current implementation works for you, that's fine. But this is a very curious approach, in which you're encumbered with the theoretical liability of singletons without enjoying all the benefits.
how to create singleton class with arguments in python
I've found out that the best way to implement Singleton is by using meta classes:
class Singleton (type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
# Python 2
class MyClass():
__metaclass__= Singleton
# Python 3
class MyClass(metaclass=Singleton):
pass
Singleton class with parameter
I don't think (exactly) what you want to do would work.
The below would work:
public static void main(String[] args)
{
Singleton.init("somepath");
...
Singleton.getInstance().doingStuff();
...
}
A better implementation may be: (which would cause a NullPointerException
if you try to use it without calling init
first) (not really Singleton any more though)
private static Singleton instance;
private SomeDataObject data;
private Singleton(String path) { loadDataFromFile(path); ... }
public static Singleton getInstance() {
return instance;
}
public static void init(String dataPath){
instance = new Singleton(dataPath);
}
Then there's: (possible bad coding practice aside)
class Main
{
public static void main(String[] args)
{
Singleton.currentPath = "somepath";
...
}
}
class Singleton
{
public static String currentPath = null;
private static Singleton instance;
private SomeDataObject data;
private Singleton(String path) { loadDataFromFile(path); ... }
public static Singleton getInstance() {
if(instance == null && currentPath != null)
instance = new Singleton(currentPath);
return instance;
}
}
which I suppose doesn't really solve much.
Can I pass parameters to a Singleton class in Swift? And general Singleton use
You can set up a singleton anyway you like. You will just have to change the way it's initialized/organized. There are some examples in this question. For some general critiques of the pattern you can read here
My own opinion is that it's generally good to avoid singletons, but sometimes they are necessary. However I tend to say singletons should only be used when the can be initialized when the app starts (App Delegate), and can/should be used and alive throughout the entire app's lifetime.
I would warn against using singletons having to do with your user interface. It appears you're capture a UITabBarController. I would strongly recommend against this, and instead use delegation or Notifications to respond to events. This is partially because of general design weirdness, but it also complicates app restoration and the memory footprint of your app.
Related Topics
Swift Switch Statement Considered All Cases of Int, But Compiler Still Display Error
Call External Function Using Watchkit Force Touch Menuitem
A Switch Bug in Swift? - "Switch Must Be Exhaustive, Consider Adding a Default Clause."
Firebase Uid VS Document-Id and Firestore Rules
Unable to Save On/Off State of a Uitableviewcell
Swift Utf8 Encoding and Non Utf8 Character
Swift 2 to 3 Migration Dispatch_Get_Global_Queue
How to Convert Uint16 to Uint8 in Swift 3
Load Desktop Version Wkwebview iOS 9
Naming Convention for Optional Binding
How to Create a Multi Line Text Field in Swiftui for MACos
Injecting a New Stylesheet into a Website via Uiwebview Using iOS8 Swift Xcode 6
Wrapping a Generic Method in a Class Extension
Fatal Error: Array Index Out of Range in Swift Xcode6
Difference Between Text("") and Text(Verbatim: "") Initializers in Swiftui