为啥在初始化程序中设置时调用 didSet?

Posted

技术标签:

【中文标题】为啥在初始化程序中设置时调用 didSet?【英文标题】: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 【参考方案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://***.com/a/25231068/294661

【讨论】:

以上是关于为啥在初始化程序中设置时调用 didSet?的主要内容,如果未能解决你的问题,请参考以下文章

结构默认初始化程序未触发 didSet

为啥我的 UICollectionView 支持方法仅在我的 ViewController 设置为初始视图控制器时调用?

在初始化程序中设置 cache_store

在 Android 应用程序中设置初始焦点

从正在运行的进程中调用函数

为啥我的状态没有在这个组件中设置