如何制作一个快速的类对象数组的深层副本
Posted
技术标签:
【中文标题】如何制作一个快速的类对象数组的深层副本【英文标题】: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.阅读此页面上的问题和第一个答案:***.com/questions/24027116/… 但是,您无法避免使用显式或隐式循环。 谢谢!我会考虑延期 【参考方案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()
以避免混淆。以上是关于如何制作一个快速的类对象数组的深层副本的主要内容,如果未能解决你的问题,请参考以下文章