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
相关产品推荐
相关产品推荐

