Static computed variable gets instantiated more than once
Static properties can be computed
but also lazy
, depending how you write them out.
- computed
meaning that their value will be re-calculate each time they are called:
private static var dateFormatter: NSDateFormatter {
print("here here") // prints each time dateFormatter its called
let formatter = NSDateFormatter()
formatter.dateFormat = "EEEE h a"
return formatter
}
- lazy
meaning that their value will be calculated once and only the first time they are called:
private static var dateFormatter: NSDateFormatter = {
print("here here") // prints only one time, when called first time
let formatter = NSDateFormatter()
formatter.dateFormat = "EEEE h a"
return formatter
}()
It took me a while to find this question when attempting to figure out the difference between a static computed property in Swift that does include =
and ()
and one that does not. @dan did a good job explaining what one should do to ensure a static property is computed only once, but in my own experimentation I came up with the following example that helped me visualize the differences between the two uses.
static var foo: String {
print("computing foo")
return "foo"
}
static var bar: String = {
print("computing bar")
return "bar"
}()
for _ in 1...3 {
print(Class.foo)
print(Class.bar)
}
The end result is:
computing foo
foo
computing bar
bar
computing foo
foo
bar
computing foo
foo
bar
foo
has the benefits of a static property, including association with the type rather than a particular instance and the inability to be overridden by a subclass. bar
, however, goes further by ensuring the property is only ever calculated one time.
Your snippet is equivalent to a get-only property, basically it's the same as:
private static var dateFormatter: NSDateFormatter {
get {
print("here here")
let formatter = NSDateFormatter()
formatter.dateFormat = "EEEE h a"
return formatter
}
}
If you only want it to run once you should define it the same way you would define a lazy property:
private static var dateFormatter: NSDateFormatter = {
print("here here")
let formatter = NSDateFormatter()
formatter.dateFormat = "EEEE h a"
return formatter
}()