【问题标题】:How to prevent from modifying a copy of dictionary如何防止修改字典副本
【发布时间】:2016-05-04 16:25:55
【问题描述】:

我遇到了以下问题。

我有一个名为 A 的函数,它将以下字典作为参数 [String : MyClass],其中 MyClass 是我创建的自定义类(它是子类NSObject)。 MyClass 有一个名为 firstProperty 的属性。

函数 A 如下所示:

func A (someDictionary : [String : MyClass]) {
    var someDictionaryCopy = someDictionary

    someDictionaryCopy["Key"].updateValue()
} 

好的,所以函数 A 主体中的 第一行 正在复制传递给函数 A 的 someDictionary。但我不想改变或修改原始的 someDictionary。

第二行:我在字典中获取一些现有值并在 MyClass 实例上运行一个方法,该方法修改了它的一个属性。

问题是,如果我运行上面的代码,传递给函数的原始字典也会被修改吗?为什么会这样?如何将字典传递给函数以使其不发生变异?

为方便起见,这里是 MyClass 实现的示例:

class MyClass : NSObject {
    var someProperty : Double = 0.0

    func updateValue() {
        someProperty += 10.0
    }
}

【问题讨论】:

  • Swift 字典是值类型 - 更新副本时修改原始字典。这与 reference 类型的 NSDictionary 相反。但是,在您的 Swift 字典中,您有一个 class:它们是引用类型,将从副本中更新。
  • 好的,那我如何复制一个字典,让里面的值不被修改?
  • 如果您不希望引用行为,则不应使用类,而应使用结构。但是如果使用类,那么就使用参考系统。这是我的建议。 :)
  • 将 MyClass 更改为结构而不是类,它将自动工作。如果这就是您所展示的 MyClass 的全部内容,那么它没有理由成为一个类。如果你已经展示了更多内容并且它需要成为一个类,那么你必须通过使你的类可复制hackingwithswift.com/example-code/system/…来启用字典的深度复制
  • 好的,谢谢大家。我知道我需要对 NSCopying 做点什么。现在一切都清楚了。我不会将我的类更改为结构,而是使其符合 NSCopying 协议 :) 另外,这是另一个关于如何实际使类符合 NSCopying 协议的有用链接:hackingwithswift.com/example-code/system/…

标签: ios swift class dictionary foundation


【解决方案1】:

问题在于MyClass 是一个引用类型。当您复制字典时,它确实会创建字典的新副本,但新副本引用了与原始字典相同的 MyClass 实例。对任何地方的 MyClass 实例的引用副本所做的更改,无论是在字典中还是在任何其他值类型中,都将反映在对同一 MyClass 实例的任何其他引用中。

基本上,字典是一种值类型,这意味着它具有值语义。但是字典中的值是引用类型,所以它们具有引用语义。解决这个问题的唯一方法是为字典中的每个键创建一个 MyClass 的新实例的字典。 或者,正如 @EricD 建议的那样,使用结构而不是类来获取您想要的值语义想要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-03
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2016-04-14
    • 2019-06-25
    • 2021-11-21
    相关资源
    最近更新 更多