What is the difference between willSet
- didSet
, and get
- set
, when working with this inside a property?
From my
get set:
get
set
are 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
Additionally you can define Read-Only Computed Properties. A read-only computed property always returns a value, and can be accessed through dot syntax, but cannot be set to a different value
Example get only property-
var number: Double {
return .pi*2
}
willSet didSet:
willSet
didSet
are Property ObserversProperty 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.
Example -
var score: Int = 0 {
willSet(newScore) {
print("willSet score to \(newScore)")
}
didSet {
print("didSet score to \(oldValue) new score is: \(score)")
}
}
score = 10
//Output
//willSet score to 10
//didSet score to 0 new score is: 10
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html
var variable1 : Int = 0 { //It's a store property
didSet {
print (variable1)
}
willSet(newValue) {
..
}
}
var variable2: Int { //It's a Computed Proprties
get {
return variable2
}
set (newValue){
}
}
For detail info of Store property and computed property
So when you are trying to assign the value into variable at that assigning time come the concept of 'didSet' & 'willSet'. As @Maxim says
Example of 'willSet' & 'didSet' :
class Number {
var variable1 : Int = 0 {
didSet{
print("didSet called")
}
willSet(newValue){
print("willSet called")
}
}
}
print("we are going to add 3")
Number().variable1 = 3
print("we added 3")
//o/p:
we are going to add 3
willSet called
didSet called
we added 3
And generally when two property are dependent at that time 'get' & 'set' used. (It's also used in protocol this is different concept.)
Example of 'get' & 'set':
class EquilateralTriangle{
var sideLength: Double = 0.0
init(sideLength: Double){
self.sideLength = sideLength
}
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
}
var triangle = EquilateralTriangle(sideLength: 3.0)
print(triangle.perimeter) //o/p: 9.0
triangle.perimeter = 12.0
print(triangle.sideLength) //o/p: 4.0
@Maxim's answer is for the 1st part of your question.
As for when to use get
and set
: when you want a computed property. This:
var x: Int
creates a stored property, which is automatically backed up by a variable (not directly accessible though). Setting a value to that property is translated in setting the value in the property, and similarly for getting.
Instead:
var y = {
get { return x + 5 }
set { x = newValue - 5}
}
will create a computed property, which is not backed up by a variable - instead you have to provide the implementation of the getter and/or setter, usually reading and writing values from another property and more generally as a result of a computation (hence the computed property name)
Suggested reading: Properties
Note: your code:
var variable2: Int {
get{
return variable2
}
set (newValue){
}
}
is wrong because in the get
you are trying to return itself, which means calling get
recursively. And in fact the compiler will warn you with a message like Attempting to access 'variable2' within its own getter
.
When and why should I use willSet/didSet
willSet
is called just before the value is stored.didSet
is called immediately after the new value is stored.Consider your example with outputs:
var variable1 : Int = 0 {
didSet{
print("didSet called")
}
willSet(newValue){
print("willSet called")
}
}
print("we are going to add 3")
variable1 = 3
print("we added 3")
Output:
we are going to add 3
willSet called
didSet called
we added 3
it works like pre/post -condition
On the other hand, you can use get
if you want to add, for example, a read-only property:
var value : Int {
get {
return 34
}
}
print(value)
value = 2 // error: cannot assign to a get-only property 'value'
You can use a regular get-and-set
syntax in case you want to implement gettable and settable property. However, you may use just get
syntax in case you implement read-only
property. With setter
you are given a newValue
property.
class GetterSetter {
var theValue: Bool = false
var property: Bool {
get { return theValue }
set {
print("Value changed from \(theValue) to \(newValue)")
theValue = newValue
}
}
}
let getterSetter = GetterSetter()
getterSetter.property = true
getterSetter.property
// PRINTS:
// Value changed from 'false' to 'true'
didSet
property observer is used in case we need to execute a code when a property has just been set. Implementing didSet
you are given oldValue
to represent the previous value.
class DidSetter {
var property: Float16 = -1.0 {
didSet {
print("Value changed from \(oldValue) to \(property)")
}
}
}
let didSetter = DidSetter()
didSetter.property = 5.0
didSetter.property
// PRINTS:
// Value changed from -1.0 to 5.0
willSet
property observer is used in case we need to execute a code before a property has been set. Implementing willSet
you are given newValue
to represent the new property value that it's going to be.
class WillSetter {
var property: String = "NO" {
willSet {
print("Value changed from \(property) to \(newValue)")
}
}
}
let willSetter = WillSetter()
willSetter.property = "YES"
willSetter.property
// PRINTS:
// Value changed from NO to YES