[Swift]: Computed Property
swift
05/12/2019
Computed Property in Swift
SWIFT
var foo: IntThis is a normal stored property while computed property looks like:
SWIFT
var foo: Int {  get {    // return caluclated value of foo  }
  set(newValue) {    // do something based on the fact that foo has changed to newValue  }}Since this is a computed property the value does not get stored but rather gets calculated inside get{}
SWIFT
set {
}- Having set{} is optional. You can just have get{} property. It then becomes read only
- set(newValue){}: newValue is a default. You can omit it and just have set{}
- You can omit get{} as well and just have a return value like below
- You can't have set{} by itself. If needed, create a func
SWIFT
var foo: Int {    // get {        return 77    }    // }}Example in Concentration
SWIFT
var indexOfOneAndOnlyFaceUpCard: Int?This was not a good idea to have it as stored property because we have to keep this variable exactly in sync with the faceUp state of all the card. This is error-prone. This can be modified to:
SWIFT
var indexOfOneAndOnlyFaceUpCard: Int?{    get {        // Check all cards to find only one that's face up. Return it, o/w return nil        var foundIndex: Int?        for index in cards.indices {            if cards[index].isFaceUp {                if foundIndex == nil {                    foundIndex = index                } else {                    return nil                }            }        }        return foundIndex    }    set {        // Make all cards face down except one at index newValue        for index in cards.indices {            cards[index]isFaceUp = (index == newValue)        }    }}Changes made in func chooseCard(at index: Int) {} after making indexOfOneAndOnlyFaceUpCard a computed property (changes are commented out):
SWIFT
func chooseCard(at index: Int) {    if !cards[index].isMatched {        if let prevIndex = indexOfOneAndOnlyFaceUp, prevIndex != index {            if cards[prevIndex].identifier == cards[index].identifier {                cards[prevIndex].isMatched = true                cards[index].isMatched = true            }                cards[index].isFaceUp = true                // indexOfOneAndOnlyFaceUp = nil        } else {            // for flipDownIndex in cards.indices {                // cards[flipDownIndex].isFaceUp = false            // }            // cards[index].isFaceUp = true            indexOfOneAndOnlyFaceUp = index        }    }}+)
- Computed property may be useful because property is often derived from other state
- If code gets messy and complicated in computed property, it may be better to implement a separate get{}, set{} methods