I am trying to deep copy a Swift class instance. As copy
and mutableCopy
function are available only for NSObject
class descendent, I am need to implement the copy function of my own for a Swift class object.
Here is what I did,
protocol Copying {
init(original: Self)
}
extension Copying {
func copy() -> Self {
return Self.init(original: self)
}
}
class A : Copying {
var name : String? = nil
var age : Int? = nil
var address : String? = nil
init(name : String) {
self.name = name
}
required init(original: A) {
//one way
self.name = original.name
self.age = original.age
self.address = original.address
//second way
let originalReflect = Mirror(reflecting: original)
let selfReflect = Mirror(reflecting: self)
for (_, originalAttr) in originalReflect.children.enumerated() {
for (_, attr) in selfReflect.children.enumerated() {
if originalAttr.label == attr.label {
//now I know the value of property and its value as well in original
//but how will I set it to self?
//If A was NSObject I could have said
self.setValue(originalAttr.value, forKey: originalAttr.label!)
}
}
}
}
}
Finally this is how I access the copy
let aInstance = A(name: "Sandeep")
let aCopy = aInstance.copy()
The first method shown in required init(original: A)
works absolutely fine, but not scalable. In my project I have base class with 50 odd property and atlas 50 more subclasses. Now I cant write the required init(original: A)
for each subclass and add self.property = original.property
that looks very much dumb way to solve it.
Second method shows the usage of Mirror to iterate through all the properties of object and but gets stuck as there is no way to set the value of self as self.setValue(for key)
is not available for swift classes.
Now I cant change the class type to NSObject for this benefit nor can I convert it to struct.
Reference :
Copy Protocol idea from : deep copy for array of objects in swift
Mirror idea from : https://www.pluralsight.com/guides/microsoft-net/property-copying-between-two-objects-using-reflection
iterate over object class attributes in Swift
Any way to solve this? Suggestions would be really helpful.