Swift Struct 实例在更新其值时发生更改

Posted

技术标签:

【中文标题】Swift Struct 实例在更新其值时发生更改【英文标题】:Swift Struct instance get changed on updating it's value 【发布时间】:2019-04-09 20:44:51 【问题描述】:

我观察到,当我们确实更改了 struct 的属性值时,会创建一个新的 struct 对象。

struct StructureTest 
    var i: Int

    mutating func changeValue(_ val: Int) 
        i = val
    


var st = StructureTest(i: 10) 
    didSet
        print("struct changed")
    


print("before: \(st)")
st.changeValue(20)
print("after: \(st)")

输出:

before: StructureTest(i: 10)   
struct changed
after: StructureTest(i: 20)

我注意到在更改它的属性值之后的主要事情。一个新的结构对象被创建并分配给var st

我确实知道什么是“值类型”以及什么是“分配时复制”功能。

但我无法理解为什么会在这里发生? 也许我在这里遗漏了一些东西? 如果您知道创建这个新结构实例的原因,请告诉我。

除此之外,我还有一个观察者:

如果我有一个结构数组。比如:

struct StructureTest 
    var i: Int

    mutating func changeValue(_ val: Int) 
        i = val
    


var arrStructs = [StructureTest(i: 10), StructureTest(i: 20)] 
    didSet 
        print("arrStructs changed")
    


arrStructs[0].changeValue(30)

输出:

arrStructs changed

我无法理解为什么要修改数组?

我可以从值类型的“写入副本”功能中了解到。 当数组被修改并且数组容量需要创建一个新数组时应该会发生这种情况,但在这种情况下,我不清楚数组修改的原因。

如果您知道背后的原因,或者您是否可以提供任何参考资料以供澄清,请告诉我。

抱歉我的语法错误。希望你清楚问题的本质。

【问题讨论】:

“我知道什么是值类型”我不认为你知道。值类型的本质是它不可变。因此,设置结构的属性意味着替换新结构。这就是为什么结构引用是可变的,必须是var 而不是let。例如,请参阅我的解释:***.com/a/49806545/341994 是的。你说的对。这就是为什么我创建了一个可变结构实例“st”。所以我可以更新它的属性。感谢您的及时反馈。 【参考方案1】:

结构具有值语义,所以当你改变一个结构时,你已经为它分配了一个新值;即你改变了变量持有的值。 swift 中的数组是一个通用结构,因此它也具有值语义(与大多数数组是引用的语言不同)。因此,如果你改变数组的任何元素,你就改变了整个数组的值。

【讨论】:

好的。因此,每当我更新结构属性时。它将创建一个新的结构实例并将其分配给“st”。那时只想再明白一件事。如果我确实有一个结构数组并且这个数组确实有 100,000 条记录。因此,如果我确实更新了任何实例属性。然后将创建一个包含 100,000 条记录的全新数组并将其分配回数组变量。我的理解对吗?还是我又错过了什么? Array 具有值 semantics 但不是值类型。因此,它实际上是作为参考实现的。 100,000 条记录的新副本只有在您有两个指向数组的东西时才会出现(这是写入时复制)。如果只有一件事引用了数组,那么编译器只会改变现有的实例。这在大多数情况下通过值语义为您提供类似性能的参考。 好的。感谢您的回答。我在堆栈溢出和其他各种站点上进行了搜索,并试图找到一种在 Swift 中打印对象地址的正确方法。那么你能验证在 Swift 5 中打印数组地址的正确方法吗? func printAddress(_ o: Any ) print(Unmanaged.passUnretained(o as AnyObject).toOpaque()) 如果在 Swift 中打印数组实例地址是一种正确的方法,那么我在这里还有一些疑问需要澄清。我无法清楚地理解。

以上是关于Swift Struct 实例在更新其值时发生更改的主要内容,如果未能解决你的问题,请参考以下文章

iOS Swift标签框高度未正确更新

当变量在 QML 中更改其值时,如何在 Qt 中执行函数?

NSPopupButton 在可可 XCode5 中更改其值时的通知

h:graphicImage 通过 f:ajax 更新其值时不会下载

Swift:结构实例不更新视图

ViewController 的实例给出错误“在展开可选值时发现 nil”