【问题标题】:In Swift, does resetting the property inside didSet trigger another didSet?在 Swift 中,重置 didSet 中的属性会触发另一个 didSet 吗?
【发布时间】:2018-03-09 01:54:01
【问题描述】:

我正在对此进行测试,看来如果您更改 didSet 中的值,您将不会再收到对 didSet 的调用。

var x: Int = 0 {
    didSet {
        if x == 9 { x = 10 }
    }
}

我可以依靠这个吗?它是否记录在某处?我在 Swift Programming Language 文档中没有看到它。

【问题讨论】:

  • 刚刚在 Xcode 8 Playground (Swift 3) 上测试并得到了相同的结果。如果您从 didSet 更改属性,didSet不会再次调用。
  • “我可以依靠这个吗”是的。
  • 实际上我的数组上有一个didSet,最后还有一个defer 用于弹出last 元素。猜猜发生了什么?它崩溃了,因为我弹出了所有使我的数组为空的元素,必须在defer 中执行if else,所以如果myArray.isEmpty != true,我不会弹出

标签: swift swift3 didset property-observer


【解决方案1】:

我还认为,这是不可能的(也许它不在 Swift 2 中),但我对其进行了测试,发现 Apple 使用了 an example。 (在“查询和设置类型属性”处)

struct AudioChannel {
    static let thresholdLevel = 10
    static var maxInputLevelForAllChannels = 0
    var currentLevel: Int = 0 {
        didSet {
            if currentLevel > AudioChannel.thresholdLevel {
                // cap the new audio level to the threshold level
                currentLevel = AudioChannel.thresholdLevel
            }
            if currentLevel > AudioChannel.maxInputLevelForAllChannels {
                // store this as the new overall maximum input level
                AudioChannel.maxInputLevelForAllChannels = currentLevel
            }
        }
    }
}

而在这段代码下面,有如下注释:

在这两个检查中的第一个中,didSet 观察者将 currentLevel 设置为不同的值。 这不会,但是,会再次调用观察者

【讨论】:

  • 这在 Swift 4 中不再适用,会导致循环
  • @thedeveloper3124 我刚刚在 Swift 4 中测试过,它仍然有效。
  • @thislooksfun 我刚刚在 Swift 5 中测试过,它会导致循环
  • 问题不在于它是否会导致循环。如果您的条件无效,它总是会导致循环。在 Apple 的情况下,它不会导致循环,因为只有在值为 > 时才会触发迭代
【解决方案2】:

From Apple docs(强调我的):

同样,如果你实现了一个 didSet 观察者,它会传递一个常量 包含旧属性值的参数。你可以命名 参数或使用 oldValue 的默认参数名称。 如果你 为它自己的 didSet 观察者中的属性分配一个值,新的 您分配的值将替换刚刚设置的值

所以,在 didSet 中赋值是正式的,不会触发无限递归。

【讨论】:

    【解决方案3】:

    它可以正常工作,但从 API 使用者的角度来看,这似乎是一个非常糟糕的主意。

    它不会递归,就像我猜想的那样,所以至少这很好。

    我能想到一些情况,在这些情况下,setter 可以更改我正在设置的内容。一个这样的例子可能是一个设置为角度的变量,它会自动归一化为[0, 2π]

    【讨论】:

    • 在 Swift 3 上进行了更改吗?我记得在 Swift 2 中递归调用实际上已经到位。
    • 在我的情况下,我将双精度舍入到最接近的其他一些值。如果不设置预舍入值,让应用程序崩溃似乎不值得。
    猜你喜欢
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    • 2020-01-17
    • 2023-04-11
    相关资源
    最近更新 更多