Infinite loop from didSet in property

protocol AProtocol {
    var someString: String { get }
}


class A: AProtocol {
    var someString: String
    init() {
        someString = "A"
    }
}


class B {
    var myProperty: AProtocol! {
        didSet {
            self.doSomething()
        }
    }


    func doSomething() {
        NSLog(self.myProperty.someString)
    }
}


let myB = B()
myB.myProperty = A() // infinite recursion




protocol AProtocol: class {
    var someString: String { get }
}


class A: AProtocol {
    var someString: String
    init() {
        someString = "A"
    }
}


class B {
    var myProperty: AProtocol! {
        didSet {
            self.doSomething()
        }
    }


    func doSomething() {
        NSLog(self.myProperty.someString)
    }
}


let myB = B()
myB.myProperty = A() // now it works


So basically if I don't impose the restriction AProtocol: class I will get an infinite loop. Basically when in doSomething I try access the just set property it will trigger the didSet block again (B.(myProperty.materializeForSet).(closure #1))


Can someone explain me why is this or confirm this is a bug in Swift?


Cheers

I cannot explain it; it's either a bug or Xcode needs to warn us when we're doing whatever we're doing that doesn't work.


If you make A and B structs (meaning that myB has to be var, not let), the infinite recursion goes away, also. 😝

Definitely looks looks like a bug.

Reported to Apple: #23202315

If you download Xcode 7.1 from the App Store and go to Help -> Release Notes, you will see this issue listed as a known issue in Swift.

Cool, I saw their workaround, but it's dangeruous if you refactor your code. I'll stick with the class restriction for now. Hopefully it'll be fixed soon : )

I started seeing this in Xcode 9.3!


I fixed it by making Protocol inherit `class`, but it is very annoying.

I understand this should change in Swift 5 :

SR-419In Swift 5 mode, when setting a property from within its own

didSet
or
willSet
observer, the observer will now only avoid being recursively called if the property is set on
self
(either implicitly or explicitly).

h ttps://github.com/apple/swift/blob/master/CHANGELOG.md

Infinite loop from didSet in property
 
 
Q