Oct 04, 2022 iOS

What is Stored and Computed property in swift

In Swift, Computed Property are a subset of a larger family of property types. The most popular properties are those that save and return a stored value; Computed properties work a little differently.

When learning to programme in Swift, all developers quickly encounter the idea of properties. One of the terms that is most frequently read, written, or discussed in programming articles, books, courses, or debates. Simply put, properties are variables and constants that we declare in Swift classes, structures, and enumerations and use to hold values. However, properties are found in all Object-Oriented Programming (OOP) languages, not just Swift.

Nevertheless, the concepts “stored” and “computed” will soon enter the conversation around properties. Even while both express their significance in some way, it is only after exploring them that one learns what they genuinely are.

What is Stored Properties

Variables or constants that hold values for instances of classes or structures are referred to as stored properties. Although it might seem apparent, variable values can always be changed. On the other hand, constants’ initial values cannot be changed after the fact.

Depending on the requirements of the application we develop, we could declare properties with default values as well. Initial values should be supplied during the initialization of the instance of the type to which a property belongs if it has merely its data type, no default value, and is not stated as optional. Keep in mind that the initial or default value for stored properties that are constants determines what the property will hold for the duration of the instance; constants are immutable and don’t change.

Class Employee { 
  var employeeName: String
  Let employeeID: Int = 12
  var department: String?
}

Three stored attributes are declared in the above Employee class. Since the employeeName parameter is of type String and lacks a default value, we will need to supply one when we create an instance of the class.

The EmployeeID is the interger and its a let constant therefore the value in the employeeID cannot be changed . It stored Property does not change the value of the EmployeeID parameter

The department parameter is used as optional in the class Employee it is supposed to store the property as optional in the Employee Class

Lazy Stored Property

One example of when to use lazy initialization is when the initial value for a property is not known until after the object is initialized or when the computation of the property is computationally expensive.

When a variable is created for the first time in Swift 4, it won’t compute the initial values thanks to a flexible attribute called a “Lazy Stored Property.” Before the variable declaration, the “lazy” modifier is used to make the variable a lazily stored property.

Use of Lazy stored Properties

  • to put off creating an entity.
  • when a property is reliant on unknowable other class components
class employee {
   lazy var eno = employeeNo()    // `var` declaration is required.
}

class employeeNo {
   var name = "Swifty"
}

var employeData = employee()
print(employeeData.employee.name)

OUTPUT

Swifty

What is a Computed Property?

A Computed property computes its property upon request—the name says it all. Adding a new property value depending on additional circumstances might be a useful addition to any of your types. This article describes their usage, when to utilise them, and the distinctions between a Computed value and a method.

Swift provides us with two different types of properties: computed properties run some code to calculate the value, and stored properties keep a value for later usage.

Here is a Student struct for comparison that has four stored properties and one Computed property. Based on merging the four stored attributes into a phrase, the Computed property produces a string.

struct Student {
    var name = "Swifty"
    var batchcolor = "blue"
    var class = "second"

    var greeting: String {
        return "Hello, my name is \(name),and I am from class \(class), and my batch color is /(batchcolor)."
    }
}

In order to access other properties and values indirectly, computed properties include a getter and an optional setter. It has several applications.

Computed properties

Before diving in, it’s helpful to be aware of a few crucial facts.

  • Consider them as bits of code that will perform a calculation each time you call them.
  • Invariably, computed characteristics are variables (never constants)
  • Classes, structs, and enums can all utilise these types of attributes.

Computed Property for Getters and Setters


All right, we’ve now shown that a Computed property produces a value. They vary from stored properties and functions in that they run some code when you call them. As of now, so nice!

Additionally, computed properties may have a unique getter and setter.

  • Each time the property is read or retrieved, a getter is run.
  • When the property is set or modified, a setter is run.
class Addition {
  var a: Int = 0
  var b: Int = 0

  // create computed property
  var add: Int {

    // retrieve value
    get {
      a + b
    }
  
    // set new value to a and b
    set(increase) {
      a = (increase + 5)
      b = (increase + 50)
    }
  }
}

var value = Addition()
value.a = 30
value.b = 40

// get value
print("Get value:", value.add)

// provide value to modify
value.add = 20

print("New a value Set:", value.a)
print("New b value Set:", value.b)

OUTPUT

Get value:70
New a value Set: 25
New a value Set: 70

We’ve generated a computed property with the name total in the aforementioned example. Within the total, we have

  1. Getter – to calculate the sum of a and b
 get {
      a + b
    }

Using “get”  in computed Properties

  • The computed property is viewable when the get keyword is used.
  • You may read data from the computed property using a getter.
  • You insert the code that will run once the computed property is invoked inside the brackets.
  • When a property is accessed, the getter is used.

2.Setter – Change the values of a and num2b

 // set new value to a and b
    set(increase) {
      a = (increase + 5)
      b = (increase + 50)
    }

Using set computed property

  • The Computed property can be modified using the set keyword. Without it, the following error occurs: It is a get-only property; you cannot set to value [your Computed property’s name].
  • You call the setter when you assign a value to the Computed property.
  • Within the setter’s braces, the value is available.
  • The compiler will automatically allot the name newValue if you do not specify a name for the given value in the setter declaration.
  • You can alter the value of other properties within the same scope by using the set method, therefore you must be aware of any dependencies connected to the Computed property.

Here, a and b can have new values assigned to them using the setter’s new value called alter.

Read only computed properties

It is required to implement the getter for a calculated property. Although it relies on the calculated property we are defining, doing so for the setter is wholly optional.

Consider a structure for storing Addition values if you want to see an illustration of that. In order to do that, we have an array and a calculated property to determine the value of the average temperature:

struct Addition {
    var add = [Double]()
    var average: Double? {
        get {
            return add.count != 0 ?
                add.reduce(0, { $0 + $1 }) / Double(add.count) :
                nil
        }
    }
}

You’ll see that there isn’t a setter present here, and it wouldn’t make sense if there were. The computed property is referred to be read-only in situations like the one described above when there is no setter.

By eliminating a few items, we can streamline the way we write read-only computed properties. Since there is no setter, it is no longer essential to explicitly specify the get body, which is the first one:

 
var average: Double? {
    return add.count != 0 ?
        add.reduce(0, { $0 + $1 }) / Double(add.count) :
        nil
}
 

By deleting the return keyword, the read-only computed property will become “lighter” as a second step. It’s not necessary to keep it in single statements:

var average: Double? {
    add.count != 0 ?
        add.reduce(0, { $0 + $1 }) / Double(add.count) :
        nil
}

The implementation of the explicit getter and the return keyword has been removed, making the computed property simpler.

Computed Properties as Property Observers in swift

In Swift, computed properties are properties that don’t store a value directly but instead provide a getter and an optional setter to retrieve or calculate a value based on other properties or external data. Property observers, on the other hand, are a way to observe and react to changes in a property’s value.

It’s not possible to directly use a computed property as a property observer in Swift. This is because computed properties don’t have a stored value that can be observed for changes.

However, you can achieve a similar effect by using property observers on the properties that your computed property depends on. For example, suppose you have a computed property that calculates the area of a rectangle based on its width and height:

var width: Double = 0 {
    didSet {
        calculateArea()
    }
}

var height: Double = 0 {
    didSet {
        calculateArea()
    }
}

var area: Double {
    return width * height
}

func calculateArea() {
    area = width * height
}

In this example, the area property is a computed property that depends on the width and height properties. To react to changes in the area property, you can add property observers to the width and height properties that call the calculateArea() function:

var width: Double = 0 {
    didSet {
        calculateArea()
    }
}

var height: Double = 0 {
    didSet {
        calculateArea()
    }
}

var area: Double = 0 {
    didSet {
        // react to changes in the area property
    }
}

func calculateArea() {
    area = width * height
}

Now, whenever the width or height properties change, the calculateArea() function is called, which updates the area property. The didSet property observer on the area property can then react to this change as needed.

Note that in this example, the area property is now a stored property rather than a computed property. This is because it’s being updated by the calculateArea() function, which is called by the property observers on the width and height properties.

Using a Computed Property to disclose rich data in swift

In Swift, you can use computed properties to disclose rich data by calculating additional information based on the values of other properties or variables.

Let’s say you have a Person class that has firstName and lastName properties. You can add a computed property called fullName that concatenates the first and last name to provide more information about the person:

class Person {
    let firstName: String
    let lastName: String
    
    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
    
    var fullName: String {
        return "\(firstName) \(lastName)"
    }
}

let person = Person(firstName: "John", lastName: "Doe")
print(person.fullName) // Output: John Doe

In the example above, the Person class has a computed property called fullName that calculates the full name of the person by concatenating the firstName and lastName properties.

When you access the fullName property on an instance of the Person class, Swift will automatically calculate the full name of the person based on the firstName and lastName properties and return it as a string. This allows you to disclose rich data about the person in a single property that is easy to access and use in your code.

You can also use computed properties to calculate other kinds of rich data, such as the age of a person based on their birthdate, the size of an image based on its width and height, or the total price of a shopping cart based on the items it contains. The possibilities are endless!

Computed Properties inside an extension in swift

In Swift, you can define computed properties inside an extension to add functionality to an existing type. Computed properties are properties that don’t store a value directly but instead provide a getter and an optional setter to retrieve or calculate a value based on other properties or external data.

Here’s an example of defining a computed property inside an extension for the Int type:

extension Int {
    var squared: Int {
        return self * self
    }
}

In this example, we define a computed property called squared for the Int type. This property returns the square of the Int value that it’s called on. Note that the self keyword refers to the instance of the Int type that the property is being called on.

Once you’ve defined a computed property inside an extension, you can use it just like any other property of the type. For example:

let number = 5
let squaredNumber = number.squared // squaredNumber is 25

In this example, we call the squared property on the number variable, which is an instance of the Int type. The result of the computation is assigned to the squaredNumber constant.

Computed properties defined inside an extension are a powerful feature of Swift that allow you to add functionality to an existing type without subclassing or modifying the original code. This can be useful when working with types that you don’t have control over, such as those provided by Apple’s frameworks.

Overriding Computed Properties in swift

In Swift, you can override a computed property in a subclass just like you can override a stored property. When you override a computed property, you provide your own implementation of the getter and/or setter for that property in the subclass.

Here’s an example of how to override a computed property in a subclass:

class Shape {
    var area: Double {
        fatalError("Subclasses must override area.")
    }
}

class Circle: Shape {
    var radius: Double
    
    init(radius: Double) {
        self.radius = radius
    }
    
    override var area: Double {
        return Double.pi * radius * radius
    }
}

In this example, we define a base class called Shape with a computed property called area. The area property is declared with a fatalError in the getter, which means that any subclasses must provide their own implementation of area.

We then define a subclass of Shape called Circle. Circle has an additional stored property called radius that’s used to calculate the area of the circle. We override the area property of Shape in Circle by providing our own implementation of the getter that calculates the area of the circle using the radius property.

Once you’ve overridden a computed property in a subclass, you can use it just like you would any other property of the subclass. For example:

let circle = Circle(radius: 5.0)
let area = circle.area // area is approximately 78.5

In this example, we create an instance of Circle with a radius of 5.0. We then call the area property on the circle instance, which returns the area of the circle based on the radius property.

Note that if you only need to add additional behavior to a computed property in a subclass, you can use the super keyword to call the implementation of the property in the superclass. For example:


class Square: Shape {
    var sideLength: Double
    
    init(sideLength: Double) {
        self.sideLength = sideLength
    }
    
    override var area: Double {
        get {
            let area = super.area // call the implementation in Shape
            print("Calculating area of square...")
            return area
        }
    }
}

In this example, we define a subclass of Shape called Square. Square has an additional stored property called sideLength that’s used to calculate the area of the square. We override the area property of Shape in Square by providing our own implementation of the getter that calls the implementation of area in Shape using the super keyword. We then add some additional behavior to the getter by printing a message before returning the area.

When should I use a Computed Property in swift

One should use a computed property in Swift when you need to provide a value that is derived from other properties or variables. Computed properties are a way to calculate values on-the-fly, based on the state of an object or the values of other properties, without storing those values directly.

Here are some scenarios where you might want to use a computed property:

  1. When you need to calculate a value based on other properties or variables: For example, if you have a Rectangle class with width and height properties, you could use a computed property called area to calculate the area of the rectangle: var area: Double { return width * height }
  2. When you need to provide a read-only property: If you want to expose a property to other parts of your code that is read-only and derived from other properties, you can use a computed property that only has a get method.
  3. When you want to perform additional logic when getting or setting a property: You can use computed properties to add additional logic to the process of getting or setting a property. For example, you could use a computed property to enforce constraints on the value of a property.
  4. When you want to abstract away implementation details: Computed properties can be used to abstract away implementation details, allowing you to expose a simpler, more high-level interface to other parts of your code. For example, you could use a computed property to convert a value from one format to another.

Overall, computed properties are a powerful tool that allow you to provide additional functionality and flexibility to your Swift classes and structs. When used appropriately, they can help you write more concise, maintainable, and expressive code.

Computed Properties vs Methods in Swift:

In Swift, computed properties and methods serve different purposes and have different use cases.

A computed property is a property that does not store a value directly, but instead calculates and returns a value on-the-fly based on the values of other properties or variables. Computed properties are accessed like regular properties, but their value is calculated on-demand when they are accessed. They are a good choice when you need to provide a value that is derived from other properties or variables, or when you want to provide a read-only property.

A method, on the other hand, is a function that can perform a specific task or operation. Methods can take arguments and return a value, and they are invoked using function call syntax. Methods are a good choice when you need to perform a complex or multi-step operation, or when you need to modify the state of an object.

Here are some guidelines for when to use computed properties versus methods:

  • Use a computed property when you need to provide a value that is derived from other properties or variables, or when you want to provide a read-only property. For example, you might use a computed property to calculate the area of a rectangle based on its width and height.
  • Use a method when you need to perform a specific task or operation, or when you need to modify the state of an object. For example, you might use a method to sort an array or to add an item to a shopping cart.
  • Use a computed property when the calculation is relatively simple and does not involve external dependencies or side effects. For more complex calculations that require external dependencies or have side effects, a method may be a better choice.
  • Use a method when the operation involves multiple steps, or when you need to pass arguments to the operation. Computed properties are not designed to take arguments or perform complex operations.

Overall, the choice between a computed property and a method depends on the specific requirements of your application and the behavior you want to implement. It’s important to choose the right tool for the job to ensure that your code is clean, efficient, and easy to understand.

Index