如何解决访问结构上的惰性属性会改变结构
我在一个结构体中有一个惰性属性,每次我访问它时,它都会改变结构体。
var numbers = [1,2,3]
struct MyStruct {
lazy var items = numbers
}
class MyClass {
var myStructPropery: MyStruct = MyStruct() {
didSet {
print(myStructPropery)
}
}
}
var myClass = MyClass()
myClass.myStructPropery.items
myClass.myStructPropery.items
myClass.myStructPropery.items
结果:
每次都会调用Print(didSet)。
理想的行为应该只是第一次突变(因为惰性变量就是这样表现的)。这是 Swift 中的错误还是我做错了什么?
解决方法
你看到的是,被观察的属性 items
已经通知它的观察者它因为被访问而发生了变异,而惰性变量根据定义是变异的,因为它将在以后设置。因此,didSet
被调用来处理这个问题。
lazy 变量实际上只设置一次,即使它表示它已经发生了变化,并且属性 myStructPropery
在第一次设置变量时只发生了一次变化,但之后是同一个实例。
这是我们如何验证这一点,首先更改惰性 var 声明,使其更像我们通常如何声明这样的变量
lazy var items: [Int] = { numbers }()
然后添加打印语句
lazy var items: [Int] = {
print("inside lazy")
return numbers
}()
如果我们现在运行测试代码
var myClass = MyClass()
myClass.myStructProperty.items
myClass.myStructProperty.items
myClass.myStructProperty.items
我们看到“inside lazy”只打印一次。要验证属性 myStructProperty
未更改,我们可以使结构符合 Equatable
并在 didSet
didSet {
if oldValue != myStructProperty {
print(myStructProperty)
}
}
现在运行测试,我们看到 didSet
中的打印永远不会执行,因此 myStructProperty 永远不会改变。
我不知道这种行为是否是一个错误,但就我个人而言,如果属性观察者在访问惰性属性后停止观察它,或者惰性变量一旦被访问就不会被定义为变异,这可能会很复杂设置。
,我通过以下设置开始调试 -
var numbers = [1,2,3]
struct MyStruct {
lazy var items = numbers
}
class MyClass {
var myStructPropery: MyStruct = MyStruct() {
didSet {
// Changed this to make sure we are not invoking getter here
print("myStructPropery setter called")
}
}
}
let myClass = MyClass()
myClass.myStructPropery.items
myClass.myStructPropery.items
myClass.myStructPropery.items
我可以使用 Xcode 12.5
在 Swift 5.4
上重现该问题。
尝试 1:将 var numbers
变成 let numbers
- 不起作用。
let numbers = [1,3]
尝试 2:在不使用额外变量的情况下内联分配值 - 不起作用。
struct MyStruct {
lazy var items = [1,3]
}
尝试 3:使用完整的 getter 语法内联分配值 - 不起作用。
struct MyStruct {
lazy var items: [Int] = {
return [1,3]
}()
}
在这一点上,我们没有选择可以尝试。尽管我们可以清楚地看到最后一次尝试中的 return [1,3]
只执行了一次,但在访问 MyClass.myStructPropery.modify
时会重复调用 items
。
也许 Swift Forums 是讨论这个更好的地方。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。