> ## Content Index
> Fetch the complete content index at: https://developerinsider.co/llms.txt
> Use this file to discover other available public pages before exploring further.

# Properties by Example - Swift Programming Language
- URL: https://developerinsider.co/properties-by-example-swift-programming-language/
- Published: 2017-12-01T16:46:07.000Z
- Updated: 2022-08-05T04:43:26.000Z
- Author: Guest
- Tags: Swift, iOS, Swift4

- `Properties` associate values with a particular `class`, `structure`, or `enumeration`.
- Suppose if we need to change or access an `iVar` in your class using an **object** of your class, then there should be **getter** and **setter** methods assigned to the iVar.
- A `property` is used mainly when other objects need to change or access the `ivars` in your **object**, without manually defining getters and setters, or using `@property` (in objective - c).
- `Properties` can be further classified into **Stored properties** and **Computed properties**.  
  - **Computed properties** are provided by `classes`, `structures`, and `enumerations`.
  - **Stored properties** are provided only by `classes` and `structures`.

## 1\. Stored Properties

- A **Stored property** is a **constant** or **variable** that is stored as part of an **instance** of a particular `class` or `structure`.
- **Stored properties** can be either be:  
  - **variable stored properties** (introduced by the `var` **keyword**).
  - **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.

#### 1.1 Stored Property of a Variable Structure Instances

```swift
struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3) // Setting Values 
print(rangeOfThreeItems.firstValue)
print(rangeOfThreeItems.length)
rangeOfThreeItems.firstValue = 6    //Modifying Values
print(rangeOfThreeItems.firstValue)  

/* prints:
0
3
6 */

```

#### 1.2 Stored Properties of Constant Structure Instances

- **If you create an instance of a structure and assign that instance to a constant, you cannot modify the instance’s properties, even if they were declared as variable properties**.

```swift
struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}

let rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3) // Setting Values 
print(rangeOfThreeItems.firstValue)
print(rangeOfThreeItems.length)

//Uncommenting next lines will give you error 
// rangeOfThreeItems.firstValue = 6    
// print(rangeOfThreeItems.firstValue)   

/* prints:
0
3*/

```

#### 1.3 Lazy Stored Properties

- A `lazy` stored property is a property **whose initial value is not calculated until the first time it is used**.
- You indicate a lazy stored property by writing the `lazy` modifier before its declaration.
- Lazy properties are useful **when the initial value for a property is dependent on outside factors** whose values are not known until after an instance’s initialization is complete.
- Lazy properties are also useful when the initial value for a property requires **complex** or **computationally expensive setup that should not be performed unless or until it is needed**.

```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")

print(manager.importer.filename)
//  DataImporter instance for the importer property has now been created

// prints: data.txt

```

#### 1.4 Stored Properties and Instance Variables

- A Swift property does not have a corresponding instance variable, and the backing store for a property is not accessed directly.
- This approach avoids confusion about how the value is accessed in different contexts and simplifies the property’s declaration into a single, definitive statement.
- All information about the property—including its name, type, and memory management characteristics—is defined in a single location as part of the type’s definition.

## 2\. Computed Properties

- In addition to stored properties, `classes`, `structures`, and `enumerations` can define computed properties, **which do not 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)

```

#### 2.1 Shorthand Setter Declaration

- If a computed property’s setter does not define a name for the new value to be set, a default name of `newValue` is used.

```swift
struct AlternativeRect {
    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 {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}
var square1 = AlternativeRect(origin: Point(x: 0.0, y: 0.0),
                  size: Size(width: 10.0, height: 10.0))
let initialSquareCenter1 = 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)

```

#### 2.2 Read-Only Computed Properties

\*A computed property with a getter but no setter is known as a read-only computed property. A read-only computed property always returns a value, and can be accessed through dot syntax, but cannot be set to a different value.

```swift
struct Cuboid {
    var width = 0.0, height = 0.0, depth = 0.0
    var volume: Double {
        return width * height * depth
    }
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")

// prints: the volume of fourByFiveByTwo is 40.0

```

## 3\. Property Observers

- Property observers observe and respond to changes in a property’s value.
- Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value.
- You can add property observers to any stored properties you define, except for lazy stored properties.
- 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.
- If you implement a `willSet` observer, it’s passed the new property value as a constant parameter. You can specify a name for this parameter as part of your willSet implementation. If you don’t write the parameter name and parentheses within your implementation, the parameter is made available with a default parameter name of `newValue`.
- If you implement a `didSet` observer, it’s passed a constant parameter containing the old property value. You can name the parameter or use the default parameter name of `oldValue`. If you assign a value to a property within its own didSet observer, the new value that you assign replaces the one that was just set.

```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 

stepCounter.totalSteps = 360 

// About to set totalSteps to 360
// Added 160 steps

stepCounter.totalSteps = 896

// About to set totalSteps to 896
// Added 536 steps

```

#### Global and Local Variables

- `Global variables` are variables that are defined **outside of any function, method, closure, or type context**.
- `Local variables` are variables that are defined **within a function, method, or closure context**.
- The global and local variables you have encountered in previous chapters have all been stored variables. Stored variables, like stored properties, provide storage for a value of a certain type and allow that value to be set and retrieved.
- you can also define computed variables and define observers for stored variables, in either a global or local scope. Computed variables calculate their value, rather than storing it, and they are written in the same way as computed properties.

## 4\. Type Properties

- `Instance properties` are properties that belong to an instance of a particular type.
- Every time you create a new instance of that type, it has its own set of property values, separate from any other instance.
- You can also define **properties that belong to the type itself, not to any one instance of that type**. There will only ever be one copy of these properties, no matter how many instances of that type you create. These kinds of properties are called `type properties`.
- Type properties are useful for defining values that are universal to all instances of a particular type, such as a constant property that all instances can use (like a static constant in C), or a variable property that stores a value that is global to all instances of that type (like a static variable in C).
- Stored type properties can be variables or constants. Computed type properties are always declared as variable properties, in the same way as computed instance properties.

```swift
struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}
print(SomeStructure.storedTypeProperty)

// Prints Some value.

SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)

// Prints Another value.

enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 6
    }
}
print(SomeEnumeration.computedTypeProperty)

// Prints 6

class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}
print(SomeClass.computedTypeProperty)

// Prints 27

```

**Next** \- [Methods by Example](https://developerinsider.co/methods-by-example-swift-programming-language/)

---

#### You can download the swift playground of all above examples from [Here](https://github.com/developerinsider/developer-insider-content/blob/master/POST/iOS/Swift/Playgrounds/Properties.playground.zip?raw=true&ref=developerinsider.co)

---