Reputation: 20058
I have the following code for a simple ViewModel with which I want to update 3 labels:
struct State {
var timeLabelText: String?
var timeLabelHidden: Bool
var dayLabelText: String
var dateLabelText: String
}
class ViewModel {
var state: State = State(timeLabelText: nil, timeLabelHidden: true, dayLabelText: "Day 0", dateLabelText: "June 19, 2017") {
didSet {
callback(state)
}
}
var callback: ((State) -> Void)
init(callback: @escaping (State) -> Void) {
self.callback = callback
callback(state)
}
var date: String {
get {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
return dateFormatter.string(from: Date())
}
}
}
This will initialize my UI with the default values from the State
. But for the dateLabelText
I want to initialize it with the actual date, before the UI is displayed.
Where is the right place to do this ? Should I just go and do it inside the ViewModel initializer ?
init(callback: @escaping (State) -> Void) {
self.callback = callback
state.dateLabelText = date // add this here
callback(state)
}
Upvotes: 0
Views: 603
Reputation: 7746
I would suggest making it a static property:
class ViewModel {
var state: State = State(timeLabelText: nil, timeLabelHidden: true, dayLabelText: "Day 0", dateLabelText: ViewModel.date) {
didSet {
callback(state)
}
}
var callback: ((State) -> Void)
init(callback: @escaping (State) -> Void) {
self.callback = callback
callback(state)
}
static private var dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
return dateFormatter
}()
static var date: String {
get {
return dateFormatter.string(from: Date())
}
}
}
Note that I also separated out the dateFormatter
so it's only initialized once. Creation of DateFormatter
s is a relatively expensive operation that shouldn't be repeated unless necessary.
Also be aware that with your approach the date will be different every time it's accessed. This type of functionality may be better described as a function rather than a property.
Upvotes: 1