【问题标题】:Why is didSet called when set inside an initializer?为什么在初始化程序中设置时调用 didSet?
【发布时间】:2019-12-22 22:47:39
【问题描述】:

我正在玩 SwiftUI,我有一个看起来像这样的类:

class Foo: ObservableObject {

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

    init() {
        self.foo = 1
    }
}

didSet 总是被调用。根据Apple docs,不应调用它。 @Published 属性包装器有什么特别之处吗?

【问题讨论】:

  • 在 Xcode 11.2.1 上测试 - didSet 在代码快照的初始化期间不会被调用。以及没有@Published
  • 我在 Xcode 11.3 (11C29) 上测试过 - 在代码快照的初始化过程中不会调用 didSet(正如 @Asperi 所写)
  • 对不起,我打错了。检查有问题的更新代码。 @Asperi

标签: swift swiftui


【解决方案1】:

所有关于类型...好的,让我们考虑代码...

案例1: @Published var foo: Int

其实是

var foo: Int
var _foo: Published<Int>

所以

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

案例 2: @Published var foo: Int!@Published var foo: Int? 也是如此)

其实是

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

所以

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

因此,IMO,答案是肯定的,@Published 很特别。

注意:如果在 self.foo = 1 行设置断点并使用 ^F7 (Control-Step Into) 在两种情况下按指令执行,您可以在运行时查看所有图片...非常有趣内部结构。

【讨论】:

    【解决方案2】:

    规则是在初始化期间不调用 setter 观察者。但是当你设置这个属性时,初始化就结束了!该属性已被赋予其初始值,即nil。因此,即使您在 init 方法中,您也不是“在初始化期间”并且 setter 观察者运行。

    【讨论】:

      【解决方案3】:

      在这里找到答案,当使用隐式解包变量时,它会离开初始化范围,因此 didSet 被称为:https://stackoverflow.com/a/25231068/294661

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-06-16
        • 1970-01-01
        • 1970-01-01
        • 2011-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多