【问题标题】:Make a shallow copy of collection classes (Array, Dictionary) in swift, not a deep copy.快速制作集合类(数组、字典)的浅拷贝,而不是深拷贝。
【发布时间】:2016-02-05 11:05:45
【问题描述】:

对此似乎有很多困惑和不同的意见,我想知道,是否可以快速制作对象的浅拷贝而不是深拷贝。

我检查了 JAVA - http://www.jusfortechies.com/java/core-java/deepcopy_and_shallowcopy.php,它通过示例清楚地解释了浅拷贝和深拷贝之间的区别,但我没有快速获得示例。

我尝试了 initWithArray:copyItems: 来检查当我更改 copyItems 的布尔标志时它有什么不同,但我没有看到任何不同。我应该通过更改 copyItems 标志来区分浅拷贝或深拷贝,但我错了,它总是创建一个深拷贝。

请检查我下面的代码,我使用 initWithArray:copyItems: 通过将 copyItems: 设置为 true 将数组对象 arrayObject1 克隆到 arrayObject2。我将 arrayObject2 第 0 个字符串对象更改为新的字符串对象,并且 arrayObject2 第 0 个对象更改了,但 arrayObject1 第 0 个对象没有更改。而如果我通过将 copyItems: 分配为 false 来复制它,那么我也会得到相同的结果。

那么如何实现浅拷贝,如果不是通过 initWithArray:copyItems: 那么 copyItems: 标志对结果的影响。

func createAnArrayUsingArrayCopyItems(){

        let name = "albort"
        let arrayObject1 = NSArray.init(objects: name, 15)
        let arrayObject2 = NSMutableArray.init(array: arrayObject1 as [AnyObject], copyItems: true)
        arrayObject2[0] = "john"
        print(arrayObject1)
        print(arrayObject2)

    }  

输出 ->

【问题讨论】:

    标签: ios arrays swift deep-copy shallow-copy


    【解决方案1】:

    这是因为 name 是一个 Swift String 实例。 String 是 struct,因此它是一个值类型。那是因为它总是按价值复制。 arrayObject1 as [AnyObject] 是对 swift Array(也是一个结构)的转换,其中包含 String 对象。

    因此,在 Swift 中使用 Array 和 String 这样的结构来获得浅拷贝并非易事。

    我只能想出将结构实例装箱到类包装器中的想法:

    class StringBox : CustomStringConvertible, NSCopying {
      var string: String
    
      init(str: String) {
        string = str
      }
    
      var description: String {
        return "\(string)"
      }
    
      @objc func copyWithZone(zone: NSZone) -> AnyObject {
        return StringBox(str: string)
      }
    }
    
    func createAnArrayUsingArrayCopyItems(){
      let name = StringBox(str: "albort")
      let arrayObject1 = NSArray.init(objects: name, 15)
      let arrayObject2 = NSMutableArray.init(array: arrayObject1 as [AnyObject], copyItems: false)
      (arrayObject2[0] as! StringBox).string = "john"
      print(arrayObject1[0])
      print(arrayObject2[0])
    }
    
    createAnArrayUsingArrayCopyItems()
    

    它给了我以下输出:

    john
    john
    

    【讨论】:

    • 您好,感谢您的回答,这是事实。但我有另一个问题,如果你能帮助我。我将 copyItems: 标志更改为 true,它因 'NSArrayThoroughConcept.StringBox' 崩溃而崩溃没有实现 methodSignatureForSelector: -- 前面的麻烦 - 无法识别的选择器 -[NSArrayThoroughConcept.StringBox copyWithZone:] 我能知道它是做什么的吗改变标志真/假的区别
    • @Kiran 我已经编辑了我的答案。您应该采用NSCopying 并实现copyWithZone: 方法以支持深拷贝。标志 copyItems 确定是通过引用复制数组项(然后通过使用适当的 ARC 工作复制对象指针进行复制)还是按值复制(然后您应该提供一种复制类项的方法)。
    • 其实这就是我想知道的,了解如何通过 array:copyItems 实现浅拷贝和深拷贝
    【解决方案2】:

    arrayObject2[0] = "john"

    这是在更改数组 2 中位置 0 处的项目 - 而不是在数组的该位置已经存在的字符串的内容。为此,它需要是一个可变字符串数组。

    确实,如果您使用可变字符串创建数组,然后附加到数组 2 中位置 0 的字符串,您将看到数组 1 中的相同字符串实例也被更新(因为它是相同的实例)。

    编辑数组实例与编辑数组中的实例不同。

    如果您要求,副本很浅。从技术上讲,浅拷贝和深拷贝有时是相同的,因为数据类型是不可变的。

    【讨论】:

    • 我明白你的回答,你能不能用一些代码解释一下,使用不是不可变的 NSMutableString
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 2016-09-27
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 2015-01-13
    相关资源
    最近更新 更多