What is the best way to make a copy of a class
, not a struct
variable without making a reference to it's memory location.
For example
class Person {
var name: String = ""
var age: Int = 0
init(name: String, age: Int) {
self.name = name
self.age = age
}
var mapped: [String: Any] {
return [
"name": self.name,
"age": self.age
]
}
}
var person: Person = Person(name: "Hitchhiker", age: 42)
var personCopy = person
var dictionary: [String: Any] {
return [
"a_person": person.mapped,
"c_personCopy": personCopy.mapped
]
}
print("Original:", dictionary.jsonStringValue)
person.age = 100
person.name = "Guide"
print("\n\n========\n\n")
print("Edit 1:", dictionary.jsonStringValue)
personCopy.age = 200
personCopy.name = "To the Galaxy"
print("\n\n========\n\n")
print("Edit 2:", dictionary.jsonStringValue)
// I have this swift extension to make my logs better, don't mind the implicit unwrapping.
extension Dictionary {
var jsonStringValue: String {
let jsonData = try! JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
return String(data: jsonData, encoding: String.Encoding.utf8)!
}
}
This prints an output which looks like this.
Original: {
"a_person" : {
"name" : "Hitchhiker",
"age" : 42
},
"c_personCopy" : {
"name" : "Hitchhiker",
"age" : 42
}
}
========
Edit 1: {
"a_person" : {
"name" : "Guide",
"age" : 100
},
"c_personCopy" : {
"name" : "Guide",
"age" : 100
}
}
========
Edit 2: {
"a_person" : {
"name" : "To the Galaxy",
"age" : 200
},
"c_personCopy" : {
"name" : "To the Galaxy",
"age" : 200
}
}
If I manipulate the values of the copies, the originals will also be, updated because the copies are assigned by reference.
I know I can create something like an extension function which makes a copy
of the original variable, like this.
extension Person {
func copy() -> Person {
return Person(name: self.name, age: self.age)
}
}
var person = Person(name: "Jon Snow", age: 0)
var personCopy = person.copy()
personCopy.name = "Jon Targaryen" // this is now a value copy.
But how can I do this easier without creating a lot of boilerplate code for a lot of different models?
Update:
I know that I can use Swift Protocols here, for example
protocol Copying {
init(original: Self)
}
extension Copying {
func copy() -> Self {
return Self.init(original: self)
}
}
Which I saw in this answer, but I'd have to subclass my Model classes to these, which may cause some problems since my Model is already a subclass and it wants me to implement some of these boilerplate initializers and I don't want that