3
protocol FooType {
    var num:Int { get set }
}

class Foo: FooType {
    var num: Int = 0 {
        didSet {
            print("Did set num")
        }
    }
}

class Bar {
    var foo: FooType = Foo() {
        didSet {
            print("Did set Foo")
        }
    }

    func changeNum(num:Int) {
        foo.num = num
    }
}

let bar = Bar()
bar.changeNum(5)

Did set num
Did set Foo

In this example, setting a property on foo causes Bar's didSet for foo to get called.

I would expect only Foo's num didSet to get called.

If I remove the protocol constraint of Bar's foo property to FooType, it behaves as I expected.

protocol FooType {
    var num:Int { get set }
}

class Foo: FooType {
    var num: Int = 0 {
        didSet {
            print("Did set num")
        }
    }
}

class Bar {
    var foo = Foo() {
        didSet {
            print("Did set Foo")
        }
    }

    func changeNum(num:Int) {
        foo.num = num
    }
}

let bar = Bar()
bar.changeNum(5)

Did set num

If I keep the conformance to FooType, but add a class constraint (FooType: class), it also behaves as expected.

protocol FooType: class {
    var num:Int { get set }
}

class Foo: FooType {
    var num: Int = 0 {
        didSet {
            print("Did set num")
        }
    }
}

class Bar {
    var foo: FooType = Foo() {
        didSet {
            print("Did set Foo")
        }
    }

    func changeNum(num:Int) {
        foo.num = num
    }
}

let bar = Bar()
bar.changeNum(5)

Did set num

If I remove the protocol completely and make Foo a struct rather than a class, we're back to both setters being called.

struct Foo {
    var num: Int = 0 {
        didSet {
            print("Did set num")
        }
    }
}

class Bar {
    var foo = Foo() {
        didSet {
            print("Did set Foo")
        }
    }

    func changeNum(num:Int) {
        foo.num = num
    }
}

let bar = Bar()
bar.changeNum(5)

Did set num
Did set Foo

In the case changing Foo to a struct, I can see why it's happening... it mentions it in the swift documentation because a struct is a value type, it makes a copy, etc. (although I didn't expect it at first).

But the other cases I don't get...

Jason C. Howlin
  • 3,858
  • 3
  • 21
  • 29
  • 2
    It seems the only problem is the first case. I guess that in `FooType` case the compiler is not sure whether you are assigning a class type or a value type. It looks like an undefined behavior. I would consider reporting a bug. – Sulthan Apr 12 '16 at 09:02
  • Did you ever resolve this? Seeing the same issue. Unfortunately, all question on Stack Overflow about this are unanswered :( https://stackoverflow.com/questions/25398753/swift-willset-didset-and-get-set-methods-in-a-property – tombardey Dec 15 '17 at 16:52

1 Answers1

0

you can solve this by conformance FooType to AnyObject

protocol FooType: AnyObject {
    var num:Int { get set }
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174