1

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?

Community
  • 1
  • 1
Ahmad F
  • 30,560
  • 17
  • 97
  • 143

1 Answers1

3

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Thanks for the clear explanation. So updating a property of `Foo` instance doesn't mean the instance itself has been reset. I think that was my misunderstanding... – Ahmad F Apr 12 '18 at 22:10
  • Also, as you mentioned in the [duplicated question](https://stackoverflow.com/questions/29453735/is-there-a-way-to-get-didset-to-work-when-changing-a-property-in-a-class), if I typed `myFoo = Foo(name: "new", age: 101)` I can see expected result on the log. – Ahmad F Apr 12 '18 at 22:14
  • 1
    Exactly: with a class, you won't see anything unless you actually _explicitly_ replace the instance with another instance. But a struct is different: it _implicitly_ replaces the instance with another instance merely because you set a property. – matt Apr 12 '18 at 22:19