how to make a deep copy of a swift array of class objects

As a simple statement, you could use code like this:

var copiedArray = array.map{$0.copy()}

Note that the term "deepCopy" is a little misleading for what you're talking about. What if the array is heterogeneous and contains other containers like arrays, dictionaries, sets, and other custom container and "leaf" objects? What you should really do is to create a protocol DeepCopiable and make it a requirement that any object that conforms to DeepCopiable require that any child objects also conform to the DeepCopiable protocol, and write the deepCopy() method to recursively call deepCopy() on all child objects. That way you wind up with a deep copy that works at any arbitrary depth.


Thanks Duncan for your solution, here is an extension using it. Note that your class must adopt the NSCopying protocol. For how to do that see here https://www.hackingwithswift.com/example-code/system/how-to-copy-objects-in-swift-using-copy

extension Array {
    func copiedElements() -> Array<Element> {
        return self.map{
            let copiable = $0 as! NSCopying
            return copiable.copy() as! Element
        }
    }
}

If Element of an array is of reference type, conform that Element with NSCopying and implement copyWithZone method.

class Book {
    var name: String

    init(_ name: String) {
        self.name  = name
    }
}

extension Book: NSCopying {
    func copy(with zone: NSZone? = nil) -> Any {
        return Book(name)
    }
}

Now implement an array extension to make a deep copy

extension Array where Element: NSCopying {
      func copy() -> [Element] {
            return self.map { $0.copy() as! Element }
      }
}

Test the code base

let b1 = Book("Book1")
let b2 = Book("Book2")

let list = [b1, b2]
let clonedList = list.copy()

clonedList is now copy of list and won't affect each-other if you make change to any of two.

Tags:

Ios

Swift