struct property changing calls didSet of the Struct each time, but class won't

Hi everyone,

See below codes,

//: Playground - noun: a place where people can play

import Foundation

struct Foo {

    var bar = 0

}

class A {

    var foo = Foo() {

        didSet {

            print("foo changed")

        }

    }

}

let a = A()

for i in 1...5 {

    a.foo.bar = i

}

// prints five times

// foo changed

// foo changed

// foo changed

// foo changed

// foo changed

If I change `struct Foo` to `class Foo`, nothing will happen.

My code depends on the class version didSet but I used the struct version.
It took me a long time to debug this out. Is this a knowledge that has been
well known already?

Xcode 9.1, Swift 4.0.2

Zhao Xin

In your example, when `Foo` is a class, then `A` does not see a mutation since the storage is out-of-line. When `Foo` is a struct, it is stored in-line and a mutation does mutate `A`.

In other words, when what’s stored in `A` is a reference, the reference itself does not get mutated when you mutate your `Foo`. If you change the statement in your loop to `a.foo = Foo()`, you’ll see that the `didSet` gets invoked again.

Cheers,
Guillaume Lessard

My code depends on the class version didSet but I used the struct version. It took me a long time to debug this out. Is this a knowledge that has been well known already?

Yes, that’s how it’s supposed to be.
It’s a feature of struct which isn’t available with classes (so considering the Objective-C past, the „surprise“ is actually that didSet is called when you do that change to a struct property).