class A { var aProperty:String = "" let bb = "hello" } struct B { let a: A var bb = "hello" } var b = B(a: A()) { didSet { print(">>>> b is set!") } } print("b: ", address(of: &b)) //"b: 0x105af48d0\n" b.a.aProperty = "change" print("b: ", address(of: &b)) //"b: 0x105af48d0\n" b.bb = "change" //">>>> b is set!" print("b: ", address(of: &b)) //"b: 0x105af48d0\n"
Changing property of regular struct(not copy-on-write) doesn’t make copy. It mutates the value. It assigns a new value to it, so didSet is called.
https://chris.eidhof.nl/post/structs-and-mutation-in-swift/
Mutating a struct variable is semantically the same as assigning a new value to it.
didSet
still needs to get triggered.With regular structs, the compiler will mutate the value in place, and not actually make a copy. With copy-on-write structs (which we’ll discuss later), this works differently.
For arrays, the memory address changes when new element is added. So for copy-on-write structs, mutating property makes copy.
var array2: [Int] = array1 print("array2:", address(of: array2)) // "array2: 0x600000885e20\n" array2.append(5) // COW print("array2:", address(of: array2)) // "array2: 0x6000039b1220\n"