Clicky

iOS Dev Nugget 287 Modifying a Property Which is a Struct Triggers didSet

.

Need to run a code review on your codebase? Hire me

Consider this code:

class S {
    var i: Int
    init(i: Int) {
        self.i = i
    }
}

class C {
    var prop1 = S(i: 0) {
        didSet {
            print("did set prop1, with i: \(prop1.i)")
        }
    }
}

var c = C()
print("i: \(c.prop1.i)")
var p = c.prop1
p.i = 1
print("i: \(c.prop1.i)")
c.prop1.i = 2

It prints:

i: 0
i: 1
i: 2

It prints 0, 1, 2 which is fairly obvious because S is a class — a reference type — so when p is actually a reference to the same instance of S, we are just operating on that same instance.

However, here's something that was surprising to me. What happens if we change S to be a struct? i.e.

Replace:

class {

with:

struct {

The output becomes:

i: 0
i: 0
did set prop1, with i: 2
i: 2

S is now a value type, so naturally, i remains at 0 because p is actually a copy of the struct held by the instance of C. Here's what surprised me though. c.prop1.i = 2 copies the struct, sets the new value of i (to 2) and assigns it back to the instance of C, triggering the didSet observer.

I recently wrote some code where this behavior bit me because I wasn't counting on didSet being triggered.

Beware!

Your feedback is valuable: Do you want more nuggets like this?   Yes   or   No

.

.

Like this and want such iOS dev nuggets to be emailed to you, weekly?

Sign Me Up! or follow @iosdevnuggets on Twitter

.

View archives of past issues