【问题标题】:how to make a deep copy of a swift array of class objects如何制作一个快速的类对象数组的深层副本
【发布时间】:2015-12-24 02:06:15
【问题描述】:

所以我知道swift数组是用struct实现的,它会自己自动复制。

我已经编写了我的课程 MyClass 并且我已经实现了 copyWithZone 来复制它

但是,我的 swift 数组包含我的 MyClass 对象,例如:

var array = [MyClass]()

当我想复制那个数组时

var anotherArray = array

它仍然没有调用MyClassObject.copyWithZone,以后如果我更改array中的对象属性,anotherArray也会反映更改。

如何在不编写 for 循环来迭代每个对象的情况下复制该

它没有被复制为deep copy for array of objects in swift,因为我不能使用 struct 来重写我的类。

【问题讨论】:

  • 不,不是,答案是我必须使用 struct 来自动复制。但是我无法将其更改为 struct。这是一堂大课。
  • 感谢您指出这一点,我将取消我的近距离投票
  • 您可能需要考虑向 Array.阅读此页面上的问题和第一个答案:stackoverflow.com/questions/24027116/… 但是,您无法避免使用显式或隐式循环。
  • 谢谢!我会考虑延期

标签: ios swift


【解决方案1】:

作为一个简单的语句,您可以使用如下代码:

var copiedArray = array.map{$0.copy()}

请注意,“deepCopy”一词对您所说的内容有点误导。如果数组是异构的并且包含其他容器,如数组、字典、集合和其他自定义容器和“叶”对象,该怎么办?你真正应该做的是创建一个协议 DeepCopiable 并要求任何符合 DeepCopiable 的对象都要求任何子对象也符合 DeepCopiable 协议,并编写 deepCopy() 方法以递归调用 deepCopy()子对象。这样你就可以得到一个可以在任意深度工作的深层副本。

【讨论】:

  • 这比 for 循环字少,这很棒;但是,为什么 swift 数组不能直接这样做呢?它应该知道它包含类对象并调用 copy()...
  • 因为它不是这样工作的。拷贝是浅拷贝。通常这就是你想要的。就内存和时间而言,深度复制的成本要高得多。
  • 所以结论是循环每个对象是唯一的解决方案?
  • 深拷贝涉及复制数组中的每个对象。在某种程度上,您必须遍历成员并复制它们。即使 Swift 数组有一个 deepCopy 方法,该方法在内部也需要遍历数组的内容并复制它们。 map 语句为您提供所需的内容,而无需编写循环。
【解决方案2】:

如果数组的元素是引用类型,则使该元素符合 NSCopying 并实现copyWithZone 方法。

class Book {
    var name: String

    init(_ name: String) {
        self.name  = name
    }
}

extension Book: NSCopying {
    func copy(with zone: NSZone? = nil) -> Any {
        return Book(name)
    }
}

现在实现一个数组扩展来进行深拷贝

extension Array where Element: NSCopying {
      func copy() -> [Element] {
            return self.map { $0.copy() as! Element }
      }
}

测试代码库

let b1 = Book("Book1")
let b2 = Book("Book2")

let list = [b1, b2]
let clonedList = list.copy()

clonedList 现在是list 的副本,如果您对其中任何一个进行更改,则不会相互影响。

【讨论】:

    【解决方案3】:

    感谢 Duncan 的解决方案,这是一个使用它的扩展程序。 请注意,您的班级必须采用 NSCopying 协议。有关如何做到这一点,请参阅此处https://www.hackingwithswift.com/example-code/system/how-to-copy-objects-in-swift-using-copy

    extension Array {
        func copiedElements() -> Array<Element> {
            return self.map{
                let copiable = $0 as! NSCopying
                return copiable.copy() as! Element
            }
        }
    }
    

    【讨论】:

    • 请注意,术语“deepCopy”有点误导。如果数组是异构的并且包含其他容器,如数组、字典、集合和其他自定义容器和“叶”对象,该怎么办?你真正应该做的是创建一个协议DeepCopiable,并要求任何符合DeepCopiable的对象要求任何子对象也符合DeepCopiable协议,并编写deepCopy()方法递归在所有子对象上调用deepCopy()。这样你就可以得到一个可以在任意深度工作的深层副本。
    • 好点。我将把函数从 deepCopy() 重命名为 copiedElements() 以避免混淆。
    猜你喜欢
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多