Singletons in Swift
A quick, relatively boring post about how to handle singletons in Swift in case you’re like me and spent an inordinate amount of time deliberating between the various approaches:
Singleton a la global variable
The laziest and easiest way to do it is storing the singleton as a global variable:
let _SingletonSharedInstance = Singleton()
class Singleton {
class var sharedInstance : Singleton {
return _SingletonSharedInstance
}
}
Advantages of this approach:
- Lazy initialization! 1
- It’s automatically threadsafe since you’re making it a constant.
The disadvantages of this approach are myriad:
- Swift doesn’t have support for private variables, so you clutter the global namespace (and you know, it’s a public variable) 2
- You can’t push it to a class-level constant 3
- Nothing says ‘this is probably a bad approach’ like prepending a variableName with an underscore
Singleton a la dispatch_once
Basically a straight port of the traditional Objective-C approach to Swift:
class RetroSingleton {
class var sharedInstance : RetroSingleton {
struct Static {
static var token : dispatch_once_t = 0
static var instance : Singleton? = nil
}
dispatch_once(& Static .token) {
Static.instance = RetroSingleton()
}
return Static.instance!
}
}
This is how Apple recommends you implement the pattern in Objective-C: for those unaware 4, dispatch_once
is a command to do something exactly once – you pass it a token and a closure to execute once, ensuring that you only hit the instantiation one time. This, like the global approach, is thread-safe and lazy: there aren’t any specific disadvantages here, but it’s not a particularly aesthetic approach.
Singleton a la nested struct
My preferred solution to the pattern (for the time being), as I find it the prettiest:
class NestedSingleton {
class var sharedInstance : NestedSingleton {
struct Static {
static let instance : NestedSingleton = NestedSingleton()
}
return Static.instance
}
}
Unlike classes, struct
s do support static constants! So we create a class-level property for the singleton class which, when accessed, grabs the struct with the singleton’d property and returns it. Since we declare the singleton’d property with let
, it shares the advantages of the previous two approaches (and only has to be calculated once.) In Barback, it looks something like this:
class AllRecipes {
class var sharedInstance : Recipe[] {
struct Static {
static let instance : Recipe[] = Static.allRecipes()
static func allRecipes() -> Recipe[] {
let filepath = NSBundle.mainBundle().pathForResource("recipes", ofType: "json")
let jsonData = NSString.stringWithContentsOfFile(filepath, encoding:NSUTF8StringEncoding, error: nil)
let recipeData = jsonData.dataUsingEncoding(NSUTF8StringEncoding)
var rawRecipes = NSJSONSerialization.JSONObjectWithData(recipeData, options: nil, error: nil) as NSDictionary[]
var allRecipes = rawRecipes.map({
(rawRecipe: NSDictionary) -> Recipe in
return Recipe(rawRecipe: rawRecipe)
})
allRecipes = sort(allRecipes) { $0.name < $1.name }
return allRecipes
}
}
return Static.instance
}
}
That’s all the approaches I’ve found. If there are other options that I haven’t considered or considerations that I haven’t made 5, lemme know! Hope this helps.
- See [here](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-XID_337 [return]
- As of beta 4, this is no longer true. Access control is now a thing. [return]
- Though Chris Lattner has mentioned that this is an eventual possibility! [return]
- Like myself, until very recently! [return]
- This is very likely. [return]