我有这个名为Meal的课程
class Meal {
var name : String = ""
var cnt : Int = 0
var price : String = ""
var img : String = ""
var id : String = ""
init(name:String , cnt : Int, price : String, img : String, id : String) {
self.name = name
self.cnt = cnt
self.price = price
self.img = img
self.id = id
}
}
我有一系列的膳食:
var ordered = [Meal]()
我想复制那个数组然后对其中一个中的Meal实例进行一些更改,而不更改第二个中的Meal实例,我该如何制作它的深层副本?
此搜索结果对我没有帮助 How do I make a exact duplicate copy of an array?
答案 0 :(得分:12)
要改进@Kametrixom,请回答以下问题: 对于普通对象,可以做的是实现支持复制的协议,并使对象类实现这样的协议:
protocol Copying {
init(original: Self)
}
extension Copying {
func copy() -> Self {
return Self.init(original: self)
}
}
然后是用于克隆的Array扩展:
extension Array where Element: Copying {
func clone() -> Array {
var copiedArray = Array<Element>()
for element in self {
copiedArray.append(element.copy())
}
return copiedArray
}
}
就是这样,查看代码和示例检查这个gist
答案 1 :(得分:9)
由于ordered
是一个快速数组,因此语句
var orderedCopy = ordered
将有效地制作原始数组的副本。
但是,由于Meal是类,因此新数组将包含引用 和原来提到的同样的饭菜。
如果你想复制膳食内容,那么在一个阵列中改变一顿饭不会改变另一个阵列中的一餐,那么你必须将膳食定义为结构,而不是类:
struct Meal {
...
来自Apple book:
使用struct创建结构。结构支持许多与类相同的行为,包括方法和初始化器。结构和类之间最重要的区别之一是结构在代码中传递时总是被复制,但类是通过引用传递的。
答案 2 :(得分:8)
正如@MarioZannone所提到的,您必须将其设为结构,因为结构会自动复制,或者您可能不需要结构并需要类。为此,您必须定义如何复制您的类。有一个NSCopying
协议在ObjC世界中统一了这个协议,但这使得你的Swift代码“不可见”,因为你必须继承NSObject
。但我建议您定义自己的复制协议,如下所示:
protocol Copying {
init(original: Self)
}
extension Copying {
func copy() -> Self {
return Self.init(original: self)
}
}
你可以像这样实现:
class Test : Copying {
var x : Int
init() {
x = 0
}
// required initializer for the Copying protocol
required init(original: Test) {
x = original.x
}
}
在初始化程序中,您必须将传递的original
Test
中的所有状态复制到self
。既然你正确地实现了协议,你可以这样做:
let original = Test()
let stillOriginal = original
let copyOriginal = original.copy()
original.x = 10
original.x // 10
stillOriginal.x // 10
copyOriginal.x // 0
这与没有ObjC的NSCopying
基本相同
编辑:可悲的是,这个非常漂亮的协议在子类化方面效果很差......
答案 3 :(得分:0)
一种简单快捷的方法是将原始数组映射到新副本中:
let copyOfPersons: [Person] = allPersons.map({(originalPerson) -> Person in
let newPerson = Person(name: originalPerson.name, age: originalPerson.age)
return newPerson
})
新人物将具有不同的指针,但值相同。
答案 4 :(得分:0)
基于之前的答案here
如果您有嵌套对象,即类的子类,那么您想要的是真正的深拷贝。
//Example
var dogsForAdoption: Array<Dog>
class Dog{
var breed: String
var owner: Person
}
所以这意味着在每个类(狗、人等)中实现 NSCopying。
你会为你的 20 节课这样做吗? 30..50..100 怎么样?你看对了吗?我们需要原生“它只是有效!”大大地。但不,我们没有。然而。
截至 2021 年 2 月,此问题尚无适当的解决方案。不过,我们有很多解决方法。
这是我一直在使用的一种,我认为限制较少的一种。
class Dog: Codable{
var breed : String = "JustAnyDog"
var owner: Person
}
class DeepCopier {
//Used to expose generic
static func Copy<T:Codable>(of object:T) -> T?{
do{
let json = try JSONEncoder().encode(object)
return try JSONDecoder().decode(T.self, from: json)
}
catch let error{
print(error)
return nil
}
}
}
//Now suppose
let dog = Dog()
guard let clonedDog = DeepCopier.Copy(of: dog) else{
print("Could not detach Dog")
return
}
//Change/mutate object properties as you want
clonedDog.breed = "rottweiler"
//Also clonedDog.owner != dog.owner, as both the owner : Person have dfferent memory allocations
如您所见,我们捎带在 Swift 的 JSONEncoder 和 JSONDecoder 上,利用 Codable 的强大功能,无论对象下有多少嵌套对象,都可以进行真正的深度复制。只需确保您的所有类都符合 Codable。
虽然它不是理想的解决方案,但它是最有效的解决方法之一。