Table of contents
1.
Introduction
2.
Type of Properties
2.1.
Stored Properties
2.1.1.
Stored Properties of Constant Structure Instances
2.1.2.
Lazy Stored Properties
2.1.3.
Stored Properties and Instance Variables
2.2.
Computed Properties
2.2.1.
Shorthand Setter Declaration
2.2.2.
Shorthand Getter Declaration
2.2.3.
Read-Only Computed Properties
3.
Frequently Asked Questions
3.1.
What are properties and methods in Swift?
3.2.
What is store property in Swift?
3.3.
What are lazy properties in Swift?
3.4.
What is binding in Swift?
4.
Conclusion
Last Updated: Mar 27, 2024

Properties of Swift

Author Aman Thakur
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Property values are associated with a specific class, structure, or enumeration. As part of an instance, stored properties hold constant and variable values, whereas computed properties calculate (rather than store) a value. Classes, structures, and enumerations all provide computed properties. Only classes and structures give stored properties.

In most cases, stored and calculated properties are linked to instances of the same type. Properties, on the other hand, can be linked to the type itself. Type properties are a type of property.

You can also create property observers to track changes in a property's value, which you can react to using custom actions. Property observers can be applied to both your own stored properties and those that a subclass inherits from its superclass.

A property wrapper may also be used to reuse code in the getter and setter of numerous properties.

Type of Properties

Stored properties and computed properties are the two types of properties.

Stored Properties

In its most basic form, a stored property is a constant or variable that is saved as part of an instance of a class or structure. Two forms of stored properties are variable stored properties (introduced by the var keyword) and constant stored properties (introduced by the constant keyword) (introduced by the let keyword).

As stated in Default Property Values, you may define a default value for a stored property as part of its definition. During startup, you may also set and change the initial value for a stored property. As stated in Assigning Constant Properties During Initialization, this is true even for constant stored properties.

The following example constructs the FixedLengthRange structure, which specifies a range of integers whose length cannot be modified once it is created:

Program

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

print(rangeOfThreeItems)
// Output: FixedLengthRange(firstValue: 6, length: 3)

FixedLengthRange instances contain a changeable firstValue stored property and a constant length stored property.Because length is a constant property, it is initialised when the new range is established and cannot be altered after that.

Stored Properties of Constant Structure Instances

You can't change the properties of a structure instance that you construct and assign to a const, even if the properties were specified as variable properties:

let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
rangeOfFourItems.firstValue = 6

Output

Even though firstValue is a variable property, it is not feasible to alter rangeOfFourItems since it is specified as a constant (using the let keyword).

This is related to the fact that structures are value types. When a value type instance is marked as a constant, all of its attributes are also marked as constants.

The same cannot be said for reference types like classes. You may still alter the variable characteristics of a reference type instance if you assign it to a constant.

Lazy Stored Properties

A lazily stored property has an initial value that isn't calculated until it's utilised for the first time. The lazy modifier is written before the declaration of a lazily stored property.

Note: Because the initial value of a lazy property may not be obtained until after instance initialization is complete, you must always declare it as a variable (with the var keyword).Constant properties cannot be designated lazy because they must always have a value before initialization is complete.

When the initial value of a property is reliant on outside factors whose values aren't known until after an instance's setup is complete, lazy properties are beneficial. When the initial value for a property involves a sophisticated or computationally costly setup that shouldn't be done until and until it's needed, lazy properties come in handy.

To minimise wasteful initialization of a complicated class, the example below employs a lazy stored property. DataImporter and DataManager are two classes defined in this example, neither of which is displayed in their entirety:

Program

class DataImporter {
   /*
   DataImporter is a class that allows you to import data from a file.    It is believed that initialising the class would take some time.
   */
   var filename = "data.txt"
   // The DataImporter class would be used to import data in this case.
}

class DataManager {
   lazy var importer = DataImporter()
   var data: [String] = []
   // the DataManager class would provide data management functionality here
}

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

print(manager.data)
// Output: ["Some data", "Some more data"]


The data stored property of the DataManager class is initialised with a fresh, empty array of String values. The objective of this DataManager class is to manage and offer access to this array of String data, even though the rest of its functionality isn't exposed.

The DataManager class has the ability to import data from a file as part of its capabilities.

The DataImporter class provides this capability, and it is believed that initialising it would take some time. This might be because a DataImporter instance must open a file and read its contents into memory when it is formed.

print(manager.importer.filename)

Note: If many threads access a property marked with the lazy modifier at the same time and the property hasn't been initialised yet, there's no assurance that the property will be initialised just once.

Stored Properties and Instance Variables

If you've worked with Objective-C before, you're probably aware that there are two methods to store values and references in a class instance.In addition to properties, instance variables may be used to back up the values contained in properties.

Swift brings these ideas together in a single property declaration. There is no instance variable for a Swift property, and the backing store for a property isn't accessible directly. This method reduces ambiguity about how the value is obtained in multiple situations and consolidates the declaration of the property into a single, decisive statement. As part of the type's specification, all information about the property is defined in one place, including its name, type, and memory management features.

Computed Properties

Classes, structures, and enumerations can define computed properties, which don't actually save a value, in addition to stored properties. Instead, they give an optional setter and a getter to indirectly get and set additional properties and values.

Program

// declaring the point
struct Point {
   var x = 0.0, y = 0.0
}

// declaring the height and width
struct Size {
   var width = 0.0, height = 0.0
}

// declaring the Reactangle
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)
       }
   }
}

// creating the object of Rectangle structure
var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))

let initialSquareCenter = square.center
// initialSquareCenter is at (5.0, 5.0)
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")

Output

Shorthand Setter Declaration

If the setter for a calculated property doesn't specify a name for the new value to be set, newValue is used by default. Here's another version of the Rect structure that makes use of the shorthand notation:

Program

// declaring the point
struct Point {
   var x = 0.0, y = 0.0
}

// declaring the height and width
struct Size {
   var width = 0.0, height = 0.0
}

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 rect = AlternativeRect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 15.0))
let initialSquareCenter = rect.center

rect.center = Point(x: 15.0, y: 15.0)
print("Rect is now at (\(rect.origin.x), \(rect.origin.y))")

Output

Shorthand Getter Declaration

If a getter's whole body is a single expression, the getter returns that expression implicitly.

This shorthand notation, as well as the shorthand notation for setters, are used in another version of the Rect structure:

Program

// declaring the point
struct Point {
   var x = 0.0, y = 0.0
}

// declaring the height and width
struct Size {
   var width = 0.0, height = 0.0
}

struct CompactRect {
   var origin = Point()
   var size = Size()
   var center: Point {
       get {
           Point(x: origin.x + (size.width / 2),
                   y: origin.y + (size.height / 2))
       }
       set {
           origin.x = newValue.x - (size.width / 2)
           origin.y = newValue.y - (size.height / 2)
       }
   }
}

var rect = CompactRect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 15.0))
let initialSquareCenter = rect.center

rect.center = Point(x: 15.0, y: 15.0)
print("Rect is now at (\(rect.origin.x), \(rect.origin.y))")

Output

Read-Only Computed Properties

A read-only computed property is a computed property that has a getter but no setter. A read-only calculated property returns a value and can be accessed using the dot syntax, but it cannot be modified.

Note: Because their value isn't fixed, computed properties—including read-only computed properties—must be declared as variable properties with the var keyword. The let keyword is exclusively used for constant properties, indicating that their values cannot be modified once they've been set during instance initialization.

By eliminating the get keyword and associated brackets from the declaration of a read-only calculated property, you may make it simpler:

Program

struct Cuboid {
   var width = 0.0, height = 0.0, depth = 0.0
   var volume: Double {
       return width * height * depth
   }
}

let _volume = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(_volume.volume)")

Output

Frequently Asked Questions

What are properties and methods in Swift?

Property values are associated with a certain class, structure, or enumeration. As part of an instance, stored properties hold constant and variable values, whereas computed properties calculate (rather than store) a value. Classes, structures, and enumerations all give computed properties.

What is store property in Swift?

In its most basic form, a stored property is a constant or variable that is saved as part of an instance of a specific class or structure. The two forms of stored properties are variable stored properties (introduced by the var keyword) and constant stored properties (introduced by the let keyword).

What are lazy properties in Swift?

A lazy var is a property that doesn't calculate its initial value until it's called for the first time. We have fixed properties, calculated properties, and changeable properties in this family of properties.

What is binding in Swift?

In SwiftUI, a binding is a link between a value and the view that shows and updates it. With the @Binding property wrapper, you may define your own bindings and provide them to views that require them.

Conclusion

If you've made it this far, it's okay to assume you enjoyed this article. This article covers the implementation of Swift Properties. You might be interested in article such as Swifty JSONSwift Nested TypesSets in Swift and many more.

Please upvote our blog to encourage other ninjas in their development, and head over to our practice platform Coding Ninjas Studio to practise top problems, attempt mock tests, read interview experiences, and much more.

Happy Learning!

Live masterclass