Let’s explore properties in Swift
There are two types of properties in Swift: Stored properties and Computed properties. Stored properties store constant and variable values as part of an instance, whereas computed properties calculate (rather than store) a value.
Stored properties:
It stores values (constant or variable) as part of an instance. It can be defined by struct or class.
Note: You can’t define stored property in extension or protocol.
Why??? 👇
Adding a new stored variable requires additional memory to be allocated to store that object. In order to allocate memory for a type (say, reserving enough room for a struct
on the stack), you need to know how large the type is. This is done at compile-time for efficiency.
Let’s take an example:
When ViewController
is instantiated, the compiler is aware of allocating memory to two stored properties. As of now, an extension is in scope so it can allocate memory to tableView
instance too. If we think about using this class in other or same module and create a private extension, then the compiler won’t be aware of how much memory to allocate for this instance. There will be a different amount of memory allocated for each ViewController
instance in a different context. Moreover, take an example of UIView
, we create an extension of UIView
and at the same time, UIView
class is internally used by UIKIt
. Multiple UIView
instances won’t be compatible in this scenario. Hence extensions are not allowed to contain stored properties.
Lazy Stored Properties:
A lazy stored property is a property whose initial value is not calculated until the first time it is used. After accessing first time, it stores value and thereafter always return stored value. Lazy property must be always declare as variable.
Lazy properties are useful when-
- initial value for a property is dependent on outside factors whose values are not known until after an instance’s initialisation is complete. Instead of creating a new method for every lazy property, you can choose to inline your setup code in the property declaration itself, using a self-executing closure. You might want to use
self
inside the closure of a lazy property. It will not cause any retain cycles. The reason is that the immediately applied closure{}()
is considered@noescape
. It does not retain the capturedself
. - initial value for a property requires complex or computationally expensive setup.
lazy
properties are marked with lazy keyword.
lazy
stored properties can be declared only in struct
or class
.
Note:
If a property marked with the lazy modifier is accessed by multiple threads simultaneously and the property has not yet been initialized, there is no guarantee that the property will be initialized only once.Computed Properties:
Computed Properties:
It doesn’t stores value. It computes and returns. It can be defined by struct, class, enum, protocol and extension.
Property observers
Property observers can be added to stored properties to observe changes or perform further action. The property observer, which is called after the assignment, is marked with the keyword didSet
, the property observer, which is called before the assignment, is marked with the keyword willSet
. didSet
` knows about oldValue
` and willSet
knows about newValue
.
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.
Property observers can be added to:
- Any stored properties you define except lazy stored properties
- Any inherited property (whether stored or computed) by overriding the property within a subclass
For a property observer, values should be declared as var
.
Note: You can’t access the computed property inside own setter or getter. It could lead to error: `All paths through this function will call itself`.
Global variables:
Global variables are variables that are defined outside of any function, method, closure, or type context. Global constants and variables are always computed lazily, in a similar manner to Lazy Stored Properties. Unlike lazy stored properties, global constants and variables do not need to be marked with the lazy
modifier.
static let key = "UserDefaultKey"
class let key = "UserDefaultKey"
properties specified with class
keyword can be inherit in subclass while properties specified with static
keyword can’t be overrided.
Public Getter, Private Setter:
You can choose to make only the setter private in Swift!
Instead of creating getCount()
we can set private setter for count
variable.