How to copy or duplicate an objects in Swift?

How to copy or duplicate an objects in Swift?

By Vinodhkumar Govindaraj , Senior iOS Developer at Evangelist Apps.

There are many occasions when you need to make a?copy?of an existing object into another one. For example, you would create a local copy of an existing data model to before writing to code data.

Before discussing how to?copyan object in Swift, let’s first explore the different techniques available.

The Swift programming language has two types of copying:

  1. Shallow Copy
  2. Deep Copy


Shallow copy

A shallow copy creates a new object that shares the same memory address as the original object. This means that any changes made to the copied object will also affect the original object, and vice versa. Shallow copies can be created using the assignment operator(=) in swift.


To illustrate this with an example, let’s say you have a class called?Studentwith a?nameproperty.

class Student {
    var name: String

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

Now, let’s create an instance of Student and make a shallow copy of it:

let originalStudent = Student("John")
print(originalStudent) // Output: John

let shallowCopy = originalStudent
originalStudent = "Amelia"
print(originalStudent.name) // Output: Amelia
print(shallowCopy.name) // Output: Amelia        

As you can see, changing the name of the original object also changed the corresponding properties of the shallow copy and vice versa.

Deep Copy

A deep copy creates a new instance of the object and also copies all of the object’s properties and sub-objects. This means that the copied object is completely independent of the original object and changes made to the copied object will not affect the original object


There are different ways to create a deep copy of an object where the any changes to the original object does not affect the copied object and vice vers. They are

1. Initialiser:

First lets create a deep copy of a Student using its initialiser method.


let deepCopy = Student(originalStudent.name)
originalStudent.name = "Smith"
print(originalStudent.name) // Output: Smith
print(deepCopy.name) // Output: Amelia        

In this case, changing the name and street properties of the original object did not affect the corresponding properties of the deep copy.

let originalStudent = Student("Leo")
print(originalStudent.name) // Output: Leo

let deepCopy = originalStudent.copy() as! Student
originalStudent.name = "Noah"
print(originalStudent.name) // Output: Noah
print(deepCopy.name) // Output: Leo        

2. Codable:

Codable?is a protocol that allows you to serialize and deserialize data between your Swift types and external formats like JSON or Property Lists.


By encoding an object and then decoding it into a new object, you can create a deep copy of that object.

To use Codable for copying an object,

1. Class should conform to the?Codable?protocol. This requires implementing the init(from:) and encode(to:) methods, which handle the encoding and decoding of the object.
2. Once your class conforms to Codable, you can use the?JSONEncoder?to encode the object into a?JSON?data representation. Then, you can use the?JSONDecoder?to decode the?JSON?data back into a new instance of the same object.

Here is an example of how to use Codable to copy an object:

struct Student: Codable {
    var name: String
}

var originalStudent = Student(_ name: "John")

let encoder = JSONEncoder()
let decoder = JSONDecoder()

do {
    let encodedData = try encoder.encode(originalStudent)
    let copiedStudent = try decoder.decode(Student.self, from: encodedData)
    originalStudent.name = "Smith"
    print(originalStudent.name) // Output: Smith
    print(copiedStudent.name) // Output: John
} catch {
    print("Error: \(error)")
}        

In this example, we first define a Student struct that conforms to Codable. We then create an instance of the Student struct and encode it into JSON using the JSONEncoder. Finally, we decode the JSON data back into a new instance of the Student struct using the JSONDecoder. The result is a deep copy of the original Student object.

NSObject:

Now we are going to create a deep copy of an object using the?copy()?method provided by NSObject and NSCopying protocol, which helps us avoid writing redundant copy code


To create a deep copy of an object using the?copy()?method provided by NSObject, our class should meet the following requirements:

  1. The class should be a subclass of NSObject.
  2. The class should conform to the NSCopying protocol. This step is not mandatory, but it makes our intent clear to the API user.
  3. The class should implement the?copy(with:)?method defined by the NSCopying protocol. This method is responsible for creating a new instance of the object and copying over the values of all its properties.

Lets modify our Student class to be of type NSObject, conform to NSCopying protocol and implement its method.

class Student: NSObject, NSCopying {

    var name: String

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

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

To make a deep copy of an object, we should call the?copy()?method on the object which we want to duplicate.

Conclusion:

In summary, a shallow copy creates a new object that points to the same memory location as the original object, while a deep copy creates a new object with a separate memory location from the original object.


Using Codable to deep copy objects in Swift is a simple and efficient technique that can save developers time and effort when working with complex objects.

Hope you enjoyed reading this article. Cheers!

#SwiftUI?#Swift.org?#evangelistapps #swiftui #iosdevelopment #coding #ios16

Andy MacLeod

Teacher at Oakwood Secondary School Horley

1 年

I think there's an error in the second block of code... To set the orginalStudent's name you would need to do: originalStudent.name = "Amelia"

回复

Well explained the concepts of Deep and shallow copy

回复

要查看或添加评论,请登录

Evangelist Apps的更多文章

社区洞察

其他会员也浏览了