I have previously used the following singleton pattern:
class Singleton {
class var sharedInstance : Singleton {
struct Static {
static let instance : Singleton = Singleton()
}
return Static.instance
}
}
When the new Xcode beta with Swift 1.2 was released I wanted to try out the new static class properties and methods. So I tried something similar to this:
class Singleton {
static let sharedInstance : Singleton = Singleton()
}
Looking at the debugger while using this it seems like a lot of nested instances of the singleton class are created by the class constant:
But looking thru the allocations it seems that only one instance are created. I guess that means it's working correctly, but I'm not seeing the same behavior with the first pattern.
What is happening here is that LLDB is showing to you the static data as if it was instance data.
Because it's static data, it does not exist "in the instance" the way normal instance data works, which causes LLDB to read memory that it should not and present it to you as if it was valid.
In general, the debugger should not show static data inside instances (compare the equivalent C++ and the way LLDB represents it).
You can verify in swift 1.2 single ton implementation that your code is correct.
It's not necesary to declare Singleton.
static let sharedInstance = Singleton()
Related
I have a NSViewController that has a class variable as follows:
class ServerAdminViewController: NSViewController, NSTextFieldDelegate, MyTableViewDelegate {
var myClass = MyClass()
func showAdmin(window: NSWindow, myClass: MyClass) {
self.myClass = myClass
window.makeKeyAndOrderFront(self)
NSApp.activate(ignoringOtherApps: true)
}
An instance of this class is instantiated in the App initialization. Later when user clicks on a menu item, I want to show a window and use that value as a singleton for the app, during the time this window is open, also being able to modify myClass. However, the line where the instance variable is declared is being executed multiple times and after the self.myClass = myClassassignment, resetting the object (this is a menubar app that opens a window).
Tried
Several things, ex. removing the parameterless constructor from myClass, declaring that variable private and with a "!", adding init methods to the ViewController (without success) and some other failed attempts.
Question
How to make myClass a singleton and share it accross the application (i.e. make it available to this window) without reinitializing it?
Soo there use to be a bunch of stuff to do this with dispatchOnce and things like that. But now the way I do this is by declaring a shared static variable on my class. This will not handle persistence but it will solve your problem creating your class many times. The shared reference with only be recreated on use after being released. Or if it has never been used before. The class variable is also handy for retrieving the class for many controllers.
class MyClass {
static let shared = MyClass()
}
class MyViewController: UIViewController {
let myClass = MyClass.shared
}
A class variable that contains the class itself, for example, the main property of the class DispatchQueue
Question 1
What kind of design pattern it is? Is this related to Singleton?
Question 2
How does the object initialized when referring this property?
Yes, it is the singleton pattern. It is all over swift like UserDefaults.standard, NotificationCenter.default, FileManager.default, ... For instance, URLSession.shared is defined in the apple docs as:
The shared singleton session object.
The singleton pattern makes sure that only one instance of the class is created. The class lazily creates its sole instance the first time it is requested and thereafter ensures that no other instance can be created.
Here is some sample code:
class MyClass {
static let shared = MyClass()
//Make the initializer private
private init(){}
//Here is a sample method
func doSomething() {
print("Doing something")
}
}
Making the initializer prevents the possibility of creating many instances, and thus the following line would yield an error:
let instance = MyClass() //MyClass initializer is inaccessible due to private protection level
To access the singleton use MyClass.shared:
let instance = MyClass.shared
instance.doSomething() //Prints: Doing something
For more details on the singleton pattern in Swift, you may look here and here.
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.
I found this in the Mozilla Firefox for iOS repository.
static let WebServerSharedInstance = WebServer()
class var sharedInstance: WebServer {
return WebServerSharedInstance
}
Why would you create a new variable that just returns the same variable when you could do the same in one line like this?
static let sharedInstance = WebServer()
I have looked into the code and I think I have misunderstood the context:
class WebServer {
static let WebServerSharedInstance = WebServer()
class var sharedInstance: WebServer {
return WebServerSharedInstance
}
}
While you can always use WebServer.WebServerSharedInstance to access the singleton, a subclass of WebServer can override sharedInstance.
class MyServer : WebServer {
override class var sharedInstance: MyServer {
return MyServer()
}
}
However, I have found no example in the code doing that so the original answer below is probably correct.
Original answer:
You are right. There is absolutely no reason to do that.
This has been probably translated directly from Objective-C, which uses similar syntax for singletons.
Also, with Swift 1.0 we weren't very sure how to create singletons and whether static let on a class is Thread safe.
I'm not sure the context. But let me explain one of the key differences between
// 1
class var sharedInstance: WebServer {
return WebServerSharedInstance
}
vs
// 2
static let sharedInstance = WebServer()
1 is computed variable which gets evaluated each time you access, while 2 get initialized lazily and evaluated only once.
If later in your code someone reassigns the WebServerSharedInstance
The 1 will return the new value while 2 will keep returning the initial value if it got initialized before.
A suggestion is that WebServerSharedInstance is a global variable declared at the top level of the file which lives as long as the file lives which is as long as the program runs --> You can use that variable in all other files
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".