You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift函数内带didSet的可选属性无法赋值问题求助

问题解释:Playground中存储属性didSet优化导致的赋值失效

问题代码

import UIKit

func test() -> Int {
    var value: Int? {
        didSet {
//            print("\(value)") // 取消注释此行,value可正常返回`1`
            print("i am triggered")
        }
    }

    let arr: [Int] = Array(0...1)
    arr.forEach { _ in
        if value != nil {
            value! += 1
        } else {
            value = 0
        }
    }

    return value ?? 999
}

print(test())

现象

当前代码输出999,说明value始终为nil;但取消didSet中打印value的语句,或者把value改成全局变量,输出就变成1。

原因分析

这是Swift编译器优化 + Playground特殊运行环境共同导致的:

  • 当你给存储属性添加didSet观察者,但观察者内部既没有访问属性的当前值(value),也没有访问旧值(oldValue)时,编译器会判定这个属性的“实际存储”是不必要的——因为看起来你只关心触发didSet的副作用,而不关心属性本身的值。
  • 在Playground这种增量编译、侧重性能优化的环境下,编译器会直接优化掉这个属性的存储逻辑:每次执行value = 0或value! += 1时,只会触发didSet里的print,但根本不会真正修改value的存储值,它始终保持初始的nil。

验证与解决

  • 取消注释print("\(value)")后,didSet中访问了属性的当前值,编译器就会保留属性的存储逻辑,赋值操作会正常生效,最终返回1。
  • 把value改成全局变量时,全局变量不会被这种局部性的优化影响,赋值逻辑自然正常执行。

内容的提问来源于stack exchange,提问作者TonyMak KW

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:37:27