As an iOS developer, dealing with objects and their copies is an integral part of your daily work. Whether you’re creating new instances, modifying existing ones, or passing data between different parts of your application, understanding the difference between shallow and deep copies is crucial. In this blog post, we’ll dive into the intricacies of these two concepts and explore when to use each one.

Let’s start with a simple analogy. Imagine you have a book sitting on your desk. A shallow copy would be like making a photocopy of the book’s cover and giving it to someone else. They’d have a new instance of the book cover, but the content inside would still be the original. In contrast, a deep copy would be like purchasing a brand-new copy of the book from the store – a completely separate instance with its own unique content.

Now, let’s translate this analogy into Swift terminology.

Shallow Copying

Shallow copying is a bit misleading in Swift because, by default, most data types in Swift are value types (like Int, String, Array, Struct), which are copied on modification. However, when it comes to reference types (like instances of a class), shallow copying refers to a concept where only the object structure is copied, but not the underlying objects it references. This means that the original object and its copy will share the same referenced objects. When you modify one, the changes reflect on the other.

Let’s consider a class Person:

class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

let original = Person(name: "John", age: 30)
let copy = original  // Shallow copy
copy.name = "Jane"

print(original.name)  // Outputs "Jane"

Here, when we create a copy version of original, both instances share the same reference to the same Person object. Therefore, when we modify the name property of copy, the change also affects in original.name.

Using shallow copying is efficient in terms of memory and execution time since no new objects are created except for the shell that holds the reference. However, you need to be certain that shared objects won’t be modified, or if changes are intended to be reflected across all references.

Deep Copying

Deep copying takes it a step further by not only copying the object but also recursively copying everything it references. The result is that the new object is completely independent of the original, with no shared references. Any changes. made to the deep copy do not affect the original object, and vice versa.

Swift’s standard library doesn’t provide a built-in way to create deep copies of objects. However, you can implement your own deep copy logic.

Taking the Person class in the previous example, we can enhance it to support deep copying by adding a method that clones the object.

class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    func clone() -> Person {
        return Person(name: this.name, age: this.age)
    }
}

let original = Person(name: "John", age: 30)
let deepCopy = original.clone()  // Deep copy
deepCopy.name = "Dave"

print(original.name)  // Outputs "John"
print(deepCopy.name)  // Outputs "Dave"

Here, deepCopy is a new Person object with the same data but independent of original. Changes to deepCopy do not affect original.

Choosing Between Shallow and Deep Copying

In general, shallow copies are more efficient because they don’t require creating copies all the nested objects. Deep copies, on the other hand, provide better encapsulation and prevent unintended side effects when modifying nested objects. However, they can be more expensive in terms of memory usage and performance, as they require creating copies of all nested objects.

The choice between them depends on the specific requirements of your application. If you need to ensure that modifications to the original object don’t affect the copied object (and vice versa), a deep copy is the way to go. However, if you don’t need this level of isolation and want to optimize for performance, a shallow copy may be sufficient.

Thanks for reading! 🚀

Categorized in: