Deep copy for an array of objects in fast

I have this class called 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 } } 

and I have a Meal array:

 var ordered = [Meal]() 

I want to duplicate this array and then make some changes to Meal instances in one of them, without changing Meal instances in the second, how would I make a deep copy of it?

This search result did not help me. How to create an exact copy of an array?

+5
source share
3 answers

Since ordered is a fast array, the operator

  var orderedCopy = ordered 

will effectively create a copy of the original array.

However, since Meal is a class , the new array will contain references to the same dishes indicated in the original.

If you also want to copy the contents of dishes so that changing food in one array does not change food in another array, you must define Meal as a struct , and not as a class:

 struct Meal { ... 

From the Apple book :

Use struct to create the structure. Structures support many of the same behaviors as classes, including methods and initializers. One of the most important differences between structures and classes is that structures are always copied when they are passed in your code, but classes are passed by reference.

+9
source

You either have to, as @MarioZannone mentioned, make it a structure, because the structures are automatically copied, or you may not need a structure and need a class. To do this, you need to determine how to copy your class. There is an NSCopying protocol that combines this in the ObjC world, but it makes your Swift code β€œunacceptable” in that you must inherit from NSObject . However, I suggest defining your own copy protocol as follows:

 protocol Copying { init(original: Self) } extension Copying { func copy() -> Self { return Self.init(original: self) } } 

which you can implement as follows:

 class Test : Copying { var x : Int init() { x = 0 } // required initializer for the Copying protocol required init(original: Test) { x = original.x } } 

Inside the initializer, you need to copy the entire state from the passed original Test to self . Now that you have executed the protocol correctly, you can do something like this:

 let original = Test() let stillOriginal = original let copyOriginal = original.copy() original.x = 10 original.x // 10 stillOriginal.x // 10 copyOriginal.x // 0 

This is basically the same as NSCopying without ObjC

EDIT: Unfortunately, this beautiful protocol works very poorly with a subclass ...

+8
source

To improve the response to @Kametrixom, check this: For ordinary objects, what can be done is to implement a protocol that supports copying, and make the class of the object implement this protocol as follows:

 protocol Copying { init(original: Self) } extension Copying { func copy() -> Self { return Self.init(original: self) } } 

And then the Array extension for cloning:

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

and it pretty much this is to view the code and sample, check this gist

+8
source

All Articles