5

I'm playing around with SwiftUI and I have a class that looks something like this:

class Foo: ObservableObject {

    @Published var foo: Int! { // Implicit unwrapped optional
        didSet {
            print("foo")
        }
    }

    init() {
        self.foo = 1
    }
}

The didSet is always called. According to Apple docs it should not be called. Is there something special going on with the @Published property wrapper?

Peter Warbo
  • 11,136
  • 14
  • 98
  • 193

3 Answers3

1

All about types... Ok, let's consider code...

case 1: @Published var foo: Int

is actually

var foo: Int
var _foo: Published<Int>

so

init() {
    self.foo = 1 // << Initialization
}

case 2: @Published var foo: Int! (the same will be for @Published var foo: Int?)

is actually

var foo: Int!
var _foo: Published<Int?> // !! Not primitive - generics class, types differ

so

init() {
    self.foo = 1 // << Assignment of Int(1)
}

Thus, IMO, answer is yes, it is something special about @Published.

Note: You can see all picture in run-time if set breakpoint at self.foo = 1 line and using ^F7 (Control-Step Into) go by instruction for both cases... very interesting internals.

Asperi
  • 228,894
  • 20
  • 464
  • 690
0

Found the answer here, when using implicit unwrapped variable it leaves the initialised scope therefor didSet is called: https://stackoverflow.com/a/25231068/294661

Peter Warbo
  • 11,136
  • 14
  • 98
  • 193
-1

The rule is that setter observers are not called during initialization. But by the time you set this property, initialization is over! The property was already given its initial value, namely nil. Therefore even though you are in an init method, you are not “during initialization” and the setter observer runs.

matt
  • 515,959
  • 87
  • 875
  • 1,141