Swift Properties
Swift properties associate values with specific classes, structures, or enumerations.
Properties can be categorized into stored properties and computed properties:
Stored Properties | Computed Properties |
---|---|
Store constant or variable values as part of an instance | Compute (rather than store) a value |
Used in classes and structures | Used in classes, structures, and enumerations |
Stored and computed properties are typically used with instance types.
Properties can also be applied directly to the type itself, known as type properties.
Additionally, property observers can be defined to monitor changes in property values, triggering a custom action. Property observers can be added to custom stored properties or inherited properties from a superclass.
Stored Properties
In simple terms, a stored property is a constant or variable that is stored as part of a specific class or structure instance.
Stored properties can be variable stored properties (defined with the var
keyword) or constant stored properties (defined with the let
keyword).
-
Default values can be specified when defining stored properties.
-
The values of stored properties can be set or modified during the construction process, even for constant stored properties.
import Cocoa
struct Number {
var digits: Int
let pi = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.pi)")
The output of the above program is:
67
3.1415
Consider the following code:
let pi = 3.1415
In this code, pi
is assigned a default value (pi = 3.1415) when the stored property is defined, so it remains unchanged regardless of when the structure is instantiated.
If you attempt to modify a constant stored property, an error will occur, as shown below:
import Cocoa
struct Number {
var digits: Int
let numbers = 3.1415
}
var n = Number(digits: 12345)
n.digits = 67
print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7
The above program will generate an error:
error: cannot assign to property: 'numbers' is a 'let' constant
n.numbers = 8.7
This indicates that 'numbers' is a constant and cannot be modified.
Lazy Stored Properties
A lazy stored property is a property whose initial value is not calculated until the first time it is used.
Use the lazy
keyword before the property declaration to denote a lazy stored property.
>
Note: Lazy properties must be defined with the var
keyword, as their values may not be available before the instance construction is complete. Constant properties must have an initial value before the construction process completes, so they cannot be declared as lazy properties.
Lazy stored properties are typically used for:
-
Delaying object creation.
-
When the property's value depends on other unknown classes.
import Cocoa
class Sample {
lazy var no = Number() // `var` keyword is mandatory
}
class Number {
var name = "tutorialpro Swift Tutorial"
}
var firstSample = Sample()
print(firstSample.no.name)
The output of the above program is:
tutorialpro Swift Tutorial
Instance Variables
If you have experience with Objective-C, you may know that Objective-C provides two ways to store values and references for class instances. For properties, instance variables can be used as backing storage for property values.
In Swift, these concepts are unified into properties. Swift properties do not have corresponding instance variables, and their backing storage cannot be directly accessed. This eliminates confusion in different access scenarios and simplifies property definitions into a single statement.
All information about a type's properties—including names, types, and memory management characteristics—is defined in one place (the type definition).
Computed Properties
In addition to stored properties, classes, structures, and enumerations can define computed properties, which do not store values directly but provide a getter to retrieve a value and an optional setter to indirectly set the values of other properties or variables.
import Cocoa
class Sample {
var no1 = 0.0, no2 = 0.0
var length = 300.0, breadth = 150.0
var middle: (Double, Double) {
get {
return (length / 2, breadth / 2)
}
set(axis) {
no1 = axis.0 - (length / 2)
no2 = axis.1 - (breadth / 2)
}
}
}
no2 = axis.1 - (breadth / 2)
}
}
}
var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)
print(result.no1)
print(result.no2)
The output of the above program execution is:
(150.0, 75.0)
-150.0
-65.0
If the setter for the computed property does not define a parameter name for the new value, the default name newValue can be used.
Read-Only Computed Properties
A computed property with only a getter and no setter is a read-only computed property.
A read-only computed property always returns a value and can be accessed through the dot (.) operator, but cannot be set to a new value.
import Cocoa
class film {
var head = ""
var duration = 0.0
var metaInfo: [String:String] {
return [
"head": self.head,
"duration":"\(self.duration)"
]
}
}
var movie = film()
movie.head = "Swift Properties"
movie.duration = 3.09
print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)
The output of the above program execution is:
Swift Properties
3.09
>
Note:
Computed properties, including read-only computed properties, must be declared with the var
keyword because their value is not fixed. The let
keyword is used to declare constant properties, which indicate values that cannot be changed after initialization.
Property Observers
Property observers monitor and respond to changes in property values. Property observers are called every time a property is set, even if the new value is the same as the current value.
Property observers can be added to stored properties except for lazy stored properties, and can also be added to inherited properties (including stored and computed properties) by overriding them.
>
Note:
The following observers can be added to a property:
willSet
is called before the new value is setdidSet
is called immediately after the new value is setwillSet
anddidSet
observers are not called during property initializationimport Cocoa class Samplepgm { var counter: Int = 0{ willSet(newTotal){ print("Counter: \(newTotal)") } didSet{ if counter > oldValue { print("Increment: \(counter - oldValue)") } } } } let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800
The output of the above program execution is:
Counter: 100
Increment: 100
Counter: 800
Increment: 700
Global and Local Variables
The patterns described for computed properties and property observers can also be applied to global and local variables.
Local Variables | Global Variables |
---|---|
Variables defined within a function, method, or closure. | Variables defined outside of functions, methods, closures, or any type. |
Used for storing and retrieving values. | Used for storing and retrieving values. |
Stored properties are used for getting and setting values. | Stored properties are used for getting and setting values. |
Also used for computed properties. | Also used for computed properties. |
Type Properties
Type properties are defined as part of the type definition within the outermost braces ({}) of the type.
The static
keyword is used to define type properties for value types, and the class
keyword is used to define type properties for classes.
struct Structname {
static var storedTypeProperty = " "
static var computedTypeProperty: Int {
// return an Int value here
}
}
enum Enumname {
static var storedTypeProperty = " "
static var computedTypeProperty: Int {
// return an Int value here
}
}
class Classname {
class var computedTypeProperty: Int {
// return an Int value here
}
}
// This returns an Int value
}
}
>
Note:
Getting and Setting Type Property Values
Similar to instance properties, type properties are accessed using the dot operator (.). However, type properties are accessed and set through the type itself, not through an instance. Here is an example:
import Cocoa
struct StudMarks {
static let markCount = 97
static var totalCount = 0
var InternalMarks: Int = 0 {
didSet {
if InternalMarks > StudMarks.markCount {
InternalMarks = StudMarks.markCount
}
if InternalMarks > StudMarks.totalCount {
StudMarks.totalCount = InternalMarks
}
}
}
}
var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()
stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)
stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)
The output of the above program is:
97
87