Using Playground.
I have the following structure:
struct Foo {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
I declared an instance from it as property observer with default values as "James" for the name
and 33 for the age
:
var myFoo = Foo(name: "James", age: 33) {
willSet {
print("my foo will be: \(newValue)")
}
didSet {
print("my foo was: \(oldValue)")
}
}
When trying to edit the name
of the instance:
myFoo.name = "John"
I could see on the log:
my foo will be: Foo(name: "John", age: 33)
my foo was: Foo(name: "James", age: 33)
which is my expectation. However, when declaring Foo
as a class instead of structure: class Foo
and running the exact same code, nothing will appear on the log.
What is the reason behind it?
Because a class is a reference type, whereas a struct is a value type.
Suppose Foo is a class. myFoo
is merely a reference. Saying myFoo.name = "John"
mutates the object in place; no new value is assigned to myFoo
, so the setter observer has nothing to observe.
Suppose Foo is a struct. That's a value type. It cannot be mutated in place. Thus, saying myFoo.name = "John"
actually replaces the struct in the variable myFoo
with a new struct; that sets the variable and the setter observer fires.
That is also why you can say myFoo.name = "John"
for a class even if myFoo
was declared with let
(i.e. the object is merely mutated in place), but you can't do that with a struct — you have to have declared myFoo
with var
so that the variable value can be replaced.