Reputation: 3725
I have a date formatter I'm trying to create as a singleton within a UITableViewCell
subclass so I've created a computed property like this:
private static var dateFormatter: NSDateFormatter {
print("here here")
let formatter = NSDateFormatter()
formatter.dateFormat = "EEEE h a"
return formatter
}
The problem is that I'm seeing the print statement more than once, which means it's getting created more than once. I've found other ways to do this (like putting in in an external class, or a class method), but I would love to understand what's happening here. Any ideas?
Upvotes: 14
Views: 5844
Reputation: 6547
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
}()
Upvotes: 1
Reputation: 315
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.
Upvotes: 8
Reputation: 9825
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
}()
Upvotes: 34
Reputation: 2176
Your static var is not a singleton, it is just a class method that creates and returns an instance of date formatter.
Check these answers of how to create a real sungleton: Using a dispatch_once singleton model in Swift
Upvotes: 0