Swift - properties
Tags: swift
Published: 2022-01-05 10:14:00

## Properties
Properties associate a value with a particular class, structure or enumeration.
- Stored properties store constant and variable values as part of an instance.
- computed properties calculate (rather than store) a value.

### Stored Properties
A stored property is a constant or variable that’s stored as part of an instance of a particular class or structure. Stored properties can be either variable stored properties (introduced by the var keyword) or constant stored properties (introduced by the let keyword).
 
You can provide a default value for a stored property as part of its definition. You can also set and modify the initial value for a stored property during initialization. This is true even for constant stored properties, 

```swift
struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// the range represents integer values 0, 1, and 2
rangeOfThreeItems.firstValue = 6
// the range now represents integer values 6, 7, and 8

```

### lazy stored properties
A lazy stored property is a property where initial value isn't calculated until the first value is used.

- lazy properties are useful when the initial value for a property is dependent on outside factors whose values aren't known until after an instance initialisation is complete.

```swift
class DataImporter {
    var filename = "data.txt"
}

class DataManager {
    lazy var importer = DataImporter()
    var data: [String] = []
}

let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// the DataImporter instance for the importer property hasn't yet been created
```
## Computed properties
In addition to stored properties, classes, structure and enumeration can define computed properties, which don't actually store a value .Instead, they provide a getter and an optional setter to retrieve and set other properties and values indirectly .

```swift
struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set(newCenter) {
            origin.x = newCenter.x - (size.width / 2)
            origin.y = newCenter.y - (size.height / 2)
        }
    }
}
var square = Rect(origin: Point(x: 0.0, y: 0.0),
                  size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// Prints "square.origin is now at (10.0, 10.0)"
```
### Read-only computed properties
A computed property with a getter but no setter is known as read-only computed property

## Property observer
Property observers observes and respond to changes in a property value.
### we can add property observer in following places
- Stored property that you define
- Stored property that you inherit
- computed property that you inherit

You have the option to define either or both of these observers on a property:

- willSet is called just before the value is stored.
- didSet is called immediately after the new value is stored.

```swift
class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            print("About to set totalSteps to \(newTotalSteps)")
        }
        didSet {
            if totalSteps > oldValue  {
                print("Added \(totalSteps - oldValue) steps")
            }
        }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
```
## Property wrappers
A property wrapper adds a layer of separation between code that manages how a property is stored and the code that defines a property.

To define a property wrapper, you make a structure, enumeration, or class that defines a wrappedValue property. 

```swift
@propertyWrapper
struct TwelveOrLess {
    private var number = 0
    var wrappedValue: Int {
        get { return number }
        set { number = min(newValue, 12) }
    }
}
//setter ensures that new value is less than 12
```

You apply a wrapper to a property by writing the wrapper’s name before the property as an attribute. 

```swift
struct SmallRectangle {
    @TwelveOrLess var height: Int
    @TwelveOrLess var width: Int
}
```