Search code examples
swiftpropertiesobservers

When should property observers run? What are the exceptions?


The behavior of property observers surprises me in the following situation. I understand that observers do not recursively call themselves, but this behavior seems to carry over to different instances of the same class, and even to instances of different subclasses.

As I understand it, property observers run any time a property is set, even if the value doesn't change, except in initialization. What exactly are the exceptions to this rule? When exactly will property observers be disregarded as seen below?

var observersCalled = 0

class ClassOne {
    var relatedOne: ClassOne?
    var relatedTwo: ClassTwo?
    var property: String = "Initial" {
        didSet {
            observersCalled += 1
            relatedOne?.property = property
            relatedTwo?.property = property
        }
    }
}

class ClassTwo {
    var property: String = "Initial" {
        didSet {
            observersCalled += 1
        }
    }
}

class Subclass: ClassOne {
    override var property: String {
        didSet {
            observersCalled += 1
        }
    }
}

let thing = ClassOne()
thing.relatedOne = ClassOne()
thing.property = "New Value"
print(observersCalled) //1 (really?)

observersCalled = 0
thing.relatedOne = nil
thing.relatedTwo = ClassTwo()
thing.property = "Another Value"
print(observersCalled) //2 (makes sense)

observersCalled = 0
thing.relatedOne = Subclass()
thing.relatedTwo = nil
thing.property = "Yet Another Value"
print(observersCalled) //1 (really!?)

Solution

  • There are no exceptions. The behavior I asked about is a bug. I have submitted a bug report for those tracking its progress.