swift中对象数组的深层复制

Als*_*ler 6 deep-copy swift

我有这个名为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
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一系列的餐:

var ordered = [Meal]()
Run Code Online (Sandbox Code Playgroud)

我想复制该数组,然后对其中一个中的Meal实例进行一些更改而不更改第二个中的Meal实例,我将如何制作它的深层副本?

此搜索结果对我没有帮助 如何制作数组的完全重复副本?

Soh*_*oun 12

要改进@Kametrixom,请检查以下内容:对于普通对象,可以实现的是实现支持复制的协议,并使对象类实现此协议,如下所示:

protocol Copying {
    init(original: Self)
}

extension Copying {
    func copy() -> Self {
        return Self.init(original: self)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后是用于克隆的Array扩展:

extension Array where Element: Copying {
    func clone() -> Array {
        var copiedArray = Array<Element>()
        for element in self {
            copiedArray.append(element.copy())
        }
        return copiedArray
    }
}
Run Code Online (Sandbox Code Playgroud)

而这就是它,查看代码和样本检查这个要点

  • 不错的方法,但是继承呢?你有什么优雅的解决方案吗? (2认同)

Mar*_*one 11

由于ordered是一个快速数组,声明

 var orderedCopy = ordered
Run Code Online (Sandbox Code Playgroud)

将有效地制作原始数组的副本.

但是,由于Meal是一个,新数组将包含对原始数组中引用的相同饭菜的引用.

如果你也想要复制膳食内容,那么在一个数组中改变一顿饭不会改变另一个阵列中的一餐,那么你必须将Meal定义为结构,而不是作为一个类:

struct Meal { 
  ...
Run Code Online (Sandbox Code Playgroud)

来自Apple书:

使用struct来创建结构.结构支持许多与类相同的行为,包括方法和初始化器.结构和类之间最重要的区别之一是结构在代码中传递时总是被复制,但类是通过引用传递的.


Kam*_*xom 8

正如@MarioZannone所提到的那样,您必须将其设为结构,因为结构会自动复制,或者您可能不需要结构并需要类.为此,您必须定义如何复制您的类.NSCopying在ObjC世界中有一个统一的协议,但这使你的Swift代码"不可见",因为你必须继承NSObject.但我建议你定义自己的复制协议,如下所示:

protocol Copying {
    init(original: Self)
}

extension Copying {
    func copy() -> Self {
        return Self.init(original: self)
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以这样实现:

class Test : Copying {
    var x : Int

    init() {
        x = 0
    }

    // required initializer for the Copying protocol
    required init(original: Test) {
        x = original.x
    }
}
Run Code Online (Sandbox Code Playgroud)

在初始化程序中,您必须将传递的所有状态复制original Testself.既然你正确地实现了协议,你可以这样做:

let original = Test()
let stillOriginal = original
let copyOriginal = original.copy()

original.x = 10

original.x         // 10
stillOriginal.x    // 10
copyOriginal.x     // 0
Run Code Online (Sandbox Code Playgroud)

这基本上与NSCopying没有ObjC的情况相同

编辑:可悲的是,这个非常漂亮的协议工作非常糟糕的子类化...