Swift property initialization
2016-01-21Let’s say we want to share a NSDateFromatter
instance in the scope of a class, for example, a UITableViewDataSource
. We would declare it like this:
class MyTableViewController: NSObject, UITableViewDataSource {
let dateFormatter: NSDateFormatter
override init() {
self.dateFormatter = NSDateFormatter()
super.init()
}
// protocol implementation skipped, not relevant in this example
}
As you can see, we need to initialize dateFormatter
in init()
. And to be sure the formatter is correctly configured, we would need to do it there too:
override init() {
self.dateFormatter = NSDateFormatter()
self.dateFormatter.dateStyle = .NoStyle
self.dateFormatter.timeStyle = .FullStyle
super.init()
}
I like to have tiny functions with explicit names.
But, as of today, we cannot factorize all of this in a method of MyTableViewController
because self
is not initialized. We need to split instanciation and configuration:
override init() {
self.dateFormatter = NSDateFormatter()
super.init()
self.configureDateFormatter()
}
func configureDateFormatter() {
self.dateFormatter.dateStyle = .NoStyle
self.dateFormatter.timeStyle = .FullStyle
}
And we need to do that for every property… not very practical.
To prevent cluttering up init()
with all the property initialization values we could do that when we declare dateFormatter
:
class MyTableViewController: NSObject, UITableViewDataSource {
let dateFormatter = NSDateFormatter()
override init() {
super.init()
self.configureDateFormatter()
}
func configureDateFormatter() {
self.dateFormatter.dateStyle = .NoStyle
self.dateFormatter.timeStyle = .FullStyle
}
// protocol implementation skipped, not relevant in this example
}
This is better and the property type is now inferred.
But I am not quite satisfied with this.
Isn’t there a way to do this in Swift without declaring and calling configureDateFormatter()
? Which is, by the way, only called once during the lifetime of the object?
Closures!
Here is how:
class MyTableViewController: NSObject, UITableViewDataSource {
let dateFormatter: NSDateFormatter = {
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .NoStyle
dateFormatter.timeStyle = .FullStyle
return dateFormatter
}()
// protocol implementation skipped, not relevant in this example
}
As you can see, we do not need to override init()
anymore! And we have all dataFormatter
initialization and configuration in one place.
Hope that someone will find this useful!