Computed Properties
iOS gives us the ability to create custom properties on our classes that can be calculated on the fly.
These properties look a lot like regular properties on a class but have a special syntax. The use curly braces after the property name along with the get
and set
methods that follow the same structure.
var displayValue: Double {
get {
return Double(display.text!)!
}
set {
display.text = String(newValue)
}
}
It's important to note that to set a value with a computed property we can use the special keyword newValue
which is whatever is evaluated on the right side of the equal sign when setting the value i.e. myProperty.text = displayValue(5.5)
We can take these principles and apply them to our model files for instance to make a property read only. They way we would do that is to only define the get
method.
import Foundation
struct MyModelStruct {
func performOperation(_ symbol: String) {
/* some operation */
}
func setOperand(_ operand: Double) {
/* set some operand */
}
var result: Double {
get {
/* get the result */
}
}
}
Property Observers
We can observe changes to any property with willSet
and didSet
. Any time the property changes these little pieces of code will get executed. So we can be notified or run code just before, just after or both when a value changes. This also works for inherited properties from superclasses.
newValue
and oldValue
are special values that you have access to inside willSet
and didSet
, that you can use for comparisons etc.
var someStoredProperty: Int = 42 {
willSet { newValue }
didSet { oldValue }
}
override var inheritedProperty: String {
willSet { newValue }
didSet { oldValue }
}
You can also set property observers on properties that are value types, like a struct, dict or array. So any time a mutation happens these snippets of code will run.
var operations: Dictionary<String, Operation> = [ ...] {
willSet {
// will be executed if an operation is added or removed
}
didSet {
// will be executed if an operation is added or removed
}
}
The most common place to use property observables is in a view controller. For instance when some piece of code is changing the background color, we might want to update a button color as well just before and after.
Lazy Properties
A lazy property does not get initialized until someone accesses it.
We can allocate an object, execute a closure, or call a method if we want.
We might want to use a lazy property because the calculations are really expensive or we're opening a network connection. With a lazy property we can delay these expensive operations.
Another reason we might want to use lazy properties is because in swift all vars must be initialized. And not only do they have to be initialized, but they all have to be initialized before we can even send a message to the class they are defined in, even internally. So we can't even call any of the classes own method until it is fully initialized.
So in the case that if one of the things we want to initialize needs to call a method on itself we are kind of stuck until the class is entirely initialized, unless we use lazy like we have on the last line below.
lazy var myColor = CreateColor()
lazy var someProp: Type = {
// construct the value of someProp here
return <the constructed value>
}()
lazy var myProperty = self.initializeMyProperty()