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
Related
I tried this with storyboard with Xcode 7 GM Seed:
import UIKit
public class C {
let _secret = arc4random_uniform(1000)
private func secret() -> String {
return "\(_secret) is a secret"
}
}
let c1 = C()
c1.secret()
This compiled and gave me the "secret". So this upsets my understanding of access control for Swift class and object. Why is this happening?
In Swift private means accessible only within the same source file which is what you're doing. If the code in your question was contained in a file C.swift and you would try to access the secret method from another Swift file you would get a compile-time error.
You can read more about the different access modifiers in the official documentation.
Swift 4 Updated answer:
There are two different access controls: fileprivate and private.
fileprivate can be accessed from their entire files.
private can only be accessed from their single declaration and extensions.
For example:
// Declaring "A" class that has the two types of "private" and "fileprivate":
class A {
private var aPrivate: String?
fileprivate var aFileprivate: String?
func accessMySelf() {
// this works fine
self.aPrivate = ""
self.aFileprivate = ""
}
}
// Declaring "B" for checking the abiltiy of accessing "A" class:
class B {
func accessA() {
// create an instance of "A" class
let aObject = A()
// Error! this is NOT accessable...
aObject.aPrivate = "I CANNOT set a value for it!"
// this works fine
aObject.aFileprivate = "I CAN set a value for it!"
}
}
For more information, check Access Control Apple's documentation, Also you could check this answer.
Is there an example of how dispatch_once should be used in Swift? (Preferably one from Apple.)
Note: In this case, I'm not using it for a singleton; I want to run arbitrary code exactly once.
Update: I'm mainly interested in the convention recommended when using this in an instance method, but usage in a class method, function, and in the global context would be useful for completeness sake.
dispatch_once_t is type alias (Int). Header documentation:
/*!
* #typedef dispatch_once_t
*
* #abstract
* A predicate for use with dispatch_once(). It must be initialized to zero.
* Note: static and global variables default to zero.
*/
typealias dispatch_once_t = Int
And here's the quote from dispatch_once documentation:
The predicate must point to a variable stored in global or static
scope. The result of using a predicate with automatic or dynamic
storage (including Objective-C instance variables) is undefined.
Token variable must be stored in global / static scope and must be initialized to zero, which leads to this code:
import Foundation
var token: dispatch_once_t = 0
dispatch_once(&token) { () -> Void in
print("Called once")
}
It doesn't work if you omit = 0 (token initialization), because compiler yields error Address of variable 'token' taken before it is initialized despite the fact that statics and globals default to zero. Tested in Xcode 7B2.
More examples based on comment. If you're inside class method you have several possibilities.
You can't declare static property inside method otherwise compiler yields Static properties may only be declared on a type error. This doesn't work:
class func doItOnce() {
static var token: dispatch_once_t = 0
...
}
Must be declared on a type. This was introduced in Swift 1.2 (Xcode 6.3 IIRC).
“static” methods and properties are now allowed in classes (as an
alias for “class final”). You are now allowed to declare static stored
properties in classes, which have global storage and are lazily
initialized on first access (like global variables). Protocols now
declare type requirements as “static” requirements instead of
declaring them as “class” requirements. (17198298)
So, what we can do if we don't like globals?
Static variable on a type
class MyClass {
private static var token: dispatch_once_t = 0
class func doItOnce() {
dispatch_once(&token) {
print("Do it once")
}
}
}
Static in a method wrapped in struct
Don't like static property on yur class? Would like to have it in your method? Wrap it in struct like this:
class func doItOnce() {
struct Tokens { static var token: dispatch_once_t = 0 }
dispatch_once(&Tokens.token) {
print("Do it once")
}
}
Actually I'm not aware of any Apple recommendation, best practice, ... how to do it for dispatch_once. Simply use whatever you like most, feels good to you and just meet criteria global / static scope.
For those of you who are curious, for me this approach has been useful for this purpose:
class SomeVC : UIViewController {
private var token: dispatch_once_t = 0
public override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
dispatch_once(&token) { () -> Void in
self.doSomethingOnce()
}
}
}
By not declaring a static var it has the expected behaviour. That being said, this is definitely NOT RECOMMENDED for any serious project, since in the Docs (as your well said) it states:
The predicate must point to a variable stored in global or static scope. The result of using a predicate with automatic or dynamic storage (including Objective-C instance variables) is undefined.
If we don't want to run into any future weird bugs and undefined behaviour I would just stick to what Apple says. But it's still nice to play around with these things, isn't it? =)
the robertvojta's answer is probably the best. because i try always to avoid import Foundation and use 'pure' Swift solution (with Swift3.0 i could change my opinion), I would like to share with you my own, very simple approach. i hope, this code is self-explanatory
class C {
private var i: Int?
func foo()->Void {
defer {
i = 0
}
guard i == nil else { return }
print("runs once")
}
}
let c = C()
c.foo() // prints "runs once"
c.foo()
c.foo()
let c1 = C()
c1.foo() // prints "runs once"
c1.foo()
class D {
static private var i: Int?
func foo()->Void {
defer {
D.i = 0
}
guard D.i == nil else { return }
print("runs once")
}
}
let d = D()
d.foo() // prints "runs once"
d.foo()
let d2 = D()
d.foo()
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()
in this example getInstance is public so it makes sense to be accessible but the private variable was accessible as well, why?
public class SingleObject {
public struct Static {
private static var object: SingleObject?
public static func getObject() -> SingleObject {
if (object == nil) {
object = SingleObject()
}
return object!
}
}
}
SingleObject.Static.object //why private is accessible here?
SingleObject.Static.getObject()
As of Swift 3, the example code no longer compiles. A new modifier called fileprivate was added and works the way private used to work (i.e. it can be seen by anything else in the same file).
private in Swift 3 and 4 now works more like you would expect it to - in Swift 3, it can only be accessed within the context it was declared in, while in Swift 4 it can also be accessed from extensions to that type (but only if they're in the same file).
The private access modifier makes a declaration private to the file and not to the class or struct. That sounds a little weird, I know, but it's how it's implemented in swift.
The other 2 access modifiers are:
internal: accessible in the current module only
public: accessible from anywhere
Suggested reading: Access Control
The private keyword means that the variable is only accessible within the same file not within the same class.
You are accessing the property from within the same file, which is why it is working. Try doing it from a different file and you will see that it is not accessible.
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".