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
idis 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
Userobjects 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.