Lesson 58Structs
Codable & Hashable
Built-in Protocols
Swift provides powerful protocols that add common functionality to your structs with minimal code. Just conform and Swift does the work!
Essential Protocols
Equatable
Compare with == and !=
struct X: EquatableHashable
Use in Set and Dictionary
struct X: HashableComparable
Compare with <, >, etc.
struct X: ComparableCodable
JSON encode/decode
struct X: CodableCodable Deep Dive
// Codable = Encodable + Decodable
struct User: Codable {
var name: String
var age: Int
}
struct User: Codable {
var name: String
var age: Int
}
CodingKeys
Use CodingKeys to map JSON keys to different property names:
case authorName = "author_name"main.swift
// CODABLE & HASHABLE
// Built-in protocols for common functionality
// ===== EQUATABLE =====
// Compare structs with ==
struct Point: Equatable {
var x: Int
var y: Int
}
let p1 = Point(x: 10, y: 20)
let p2 = Point(x: 10, y: 20)
let p3 = Point(x: 5, y: 5)
print(p1 == p2) // true
print(p1 == p3) // false
// ===== HASHABLE =====
// Use structs in Sets and as Dictionary keys
struct User: Hashable {
var id: Int
var name: String
}
let user1 = User(id: 1, name: "Alice")
let user2 = User(id: 2, name: "Bob")
var userSet: Set<User> = [user1, user2]
var userScores: [User: Int] = [user1: 100, user2: 85]
print(userScores[user1]!) // 100
// ===== COMPARABLE =====
// Enable <, >, <=, >= comparisons
struct Score: Comparable {
var points: Int
var name: String
static func < (lhs: Score, rhs: Score) -> Bool {
return lhs.points < rhs.points
}
}
let scores = [
Score(points: 85, name: "Alice"),
Score(points: 92, name: "Bob"),
Score(points: 78, name: "Charlie")
]
let sorted = scores.sorted() // Sorted by points
print(sorted.map { $0.name }) // ["Charlie", "Alice", "Bob"]
// ===== CODABLE =====
// Encode/decode to JSON, PropertyList, etc.
struct Product: Codable {
var id: Int
var name: String
var price: Double
var inStock: Bool
}
let product = Product(id: 1, name: "iPhone", price: 999.99, inStock: true)
// ENCODE TO JSON
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
if let jsonData = try? encoder.encode(product),
let jsonString = String(data: jsonData, encoding: .utf8) {
print(jsonString)
// {
// "id" : 1,
// "name" : "iPhone",
// "price" : 999.99,
// "inStock" : true
// }
}
// DECODE FROM JSON
let jsonString = """
{
"id": 2,
"name": "MacBook",
"price": 1299.99,
"inStock": false
}
"""
let decoder = JSONDecoder()
if let data = jsonString.data(using: .utf8),
let decoded = try? decoder.decode(Product.self, from: data) {
print(decoded.name) // MacBook
}
// CUSTOM CODING KEYS
struct Article: Codable {
var title: String
var body: String
var authorName: String
enum CodingKeys: String, CodingKey {
case title
case body = "content"
case authorName = "author_name"
}
}
// NESTED CODABLE
struct Order: Codable {
var orderId: Int
var customer: Customer
var items: [OrderItem]
}
struct Customer: Codable {
var name: String
var email: String
}
struct OrderItem: Codable {
var productId: Int
var quantity: Int
}Try It Yourself!
Create a Book struct that's Codable with custom CodingKeys. Encode it to JSON and decode it back!