[Swift] Identifiable, Codable, Hashable Protocols

Protocols play an important role in Swift. A protocol is an interface that defines the properties and methods required to perform a specific task, and types that adopt the protocol must implement its requirements. In this post, I will explain the Identifiable, Codable, and Hashable protocols, which are useful when creating user models.

User Model Struct Definition Example

Below is code that defines a struct named User and adopts the Identifiable, Codable, and Hashable protocols.


import Foundation

struct User: Identifiable, Codable, Hashable {
    let id: String
    let fullname: String
    let email: String
    let username: String
    let profileImageUrl: String?
    let bio: String?

    init(
        id: String,
        fullname: String,
        email: String,
        username: String,
        profileImageUrl: String? = nil,
        bio: String? = nil)
    {
        self.id = id
        self.fullname = fullname
        self.email = email
        self.username = username
        self.profileImageUrl = profileImageUrl
        self.bio = bio
    }
}

This struct is a model defined to hold user information. The most notable part of the code above is that it adopts three protocols: Identifiable, Codable, and Hashable. Now, I will explain what each protocol means and why they are important in this code.


1. Identifiable Protocol

The Identifiable protocol is closely related to SwiftUI. Since SwiftUI needs to uniquely identify each item when rendering a list, the Identifiable protocol provides a unique identifier for this purpose.

Requirements

The Identifiable protocol requires an id property, which must be unique. In the User struct, id is defined as a String type, and users are uniquely identified through this value.

Benefits

  • Compatibility with SwiftUI: When rendering lists or data in SwiftUI, an id is needed to identify each item. This protocol provides support for that automatically.
  • Unique Data Management: Since users are distinguished by their id, it is easy to manage unique items in a list without duplication.

Example Code


let user1 = User(id: "123", fullname: "John Doe", email: "john@example.com", username: "johnny")
let user2 = User(id: "456", fullname: "Jane Doe", email: "jane@example.com", username: "janedoe")

let users = [user1, user2]

When used in a SwiftUI list, each item in the users array is identified by its id value.


2. Codable Protocol

The Codable protocol allows you to convert objects to and from external data formats such as JSON. It is a combination of two protocols (Encodable and Decodable), allowing for easy serialization (encoding) or deserialization (decoding) of objects.

Requirements

Codable essentially provides the ability to automatically serialize and deserialize all properties of a struct. This means you can convert JSON data into a Swift User object, or vice-versa, without writing any extra code.

Benefits

  • Network Communication: It is easy to convert JSON data received from an API into Swift objects, and it is also useful when sending data to a server.
  • File Storage: When saving user data to a file, you can easily convert the object to JSON format for storage.

Example Code


// Encode User object to JSON
let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(user1) {
    print(String(data: jsonData, encoding: .utf8)!)
}

// Decode JSON into User object
let decoder = JSONDecoder()
if let decodedUser = try? decoder.decode(User.self, from: jsonData) {
    print(decodedUser)
}


3. Hashable Protocol

The Hashable protocol allows an object to be hashed. A hash function generates an integer value used to uniquely identify an object, which enables the object to be used in collections such as Sets or Dictionaries.

Requirements

The Hashable protocol requires that an object have a unique integer value called hashValue. However, in most cases, Swift generates this value automatically.

Benefits

  • Usable in Sets and Dictionaries: You can use User objects as elements in a Set or as keys in a Dictionary.
  • Fast Searching: Data can be searched quickly using the hash value.

Example Code


var userSet: Set<User> = [user1, user2]
let userDict: [User: String] = [user1: "First User", user2: "Second User"]

If the User struct does not conform to Hashable, it cannot be used in a Set or Dictionary. By adopting Hashable, a unique hash value is generated for the object, making it usable.


Conclusion

The Identifiable, Codable, and Hashable protocols are very useful in Swift, and are frequently used when defining data models. By using these three protocols together, you can efficiently handle various requirements such as data management in the UI, API communication, and fast data searching within collections. I hope the user model example introduced in this post helps you better understand how to utilize protocols in Swift.

AD