I had this implementation with Swift 2.0 and the Xcode suggestion is not only baffling but causes compilation error as well. it's a library where users are passing callfunc closures.
Before
protocol MyProtocol {
}
class Main
private static var t: dispatch_once_t = 0
private static var singleton: MyProtocol?
public class func getSingleton(callfunc: () -> MyProtocol) -> MyProtocol {
dispatch_once(&self.t) {
self.singleton = callfunc()
}
return singleton!
}
After
private static var __once: () = {
MyProtocol.singleton = callfunc()
}()
open class func getSingleton(_ callfunc: () -> MyProtocol) -> MyProtocol {
singleton = MyProtocol.__once()
return singleton!
}
I basically need to pass parameter to __once function.
USER:
class Test: MyProtocol {
}
Main.getSingleton({Test()});
It's not a duplicate of Using a dispatch_once singleton model in Swift, a closure is being passed, it's a .framework and closure is passed in by the user of the library.
This works (as in it won't call
callfunc
twice), if you don't mind the function becomes@escaping
:Note that this does not address thread safety (
CALLER
can be changed before reachingGETTER
), and theCALLER
will be overwritten every timegetSingleton
is used which may impose some performance penalty.I usually like this pattern:
final class MyClass { static let shared = MyClass() }
Then you can call MyClass.shared to get your singleton.
Create a singleTon class as follows :
Example usage :
Output :
i am born
hello
hello
As you noticed Initializer is only called once. As per apple docs :
“The lazy initializer for a global variable (also for static members of structs and enums) is run the first time that global is accessed, and is launched as
dispatch_once
to make sure that the initialization is atomic. This enables a cool way to usedispatch_once
in your code: just declare a global variable with an initializer and mark it private.”Explaining Comments :
Static member of class implicitly calls "dispatch_once" hence it is thread safe.
Making init private prevents initialisation again.
Test code line to prove initialisation is private.
The answers to date are great, but I like to be able to test my classes that use singleton with unit tests. The existing solutions require that you get a real singleton, not one that you can Fake, Mock, and Stub. In order to make testing easier, I use something like this:
In classes under test that use the singleton, I can do something like this:
Another way, for me which is good enough using init private