Lesson 60Structs
Structs Practice
Module Complete!
Time to practice everything you've learned about structs. Complete these exercises to solidify your understanding!
Exercises Overview
1. Basic Struct
Book with properties & methods
2. Protocol Conformance
Shapes with Shape protocol
3. Codable JSON
Parse API responses
4. Shopping Cart
Complex struct system
5. Value Types
Copy-on-assignment demo
What You've Learned
- Struct basics and properties
- Methods and mutating keyword
- Initializers (memberwise, custom, failable)
- Value types vs reference types
- Extensions for organizing code
- Protocols (Equatable, Hashable, Codable)
- Best practices for clean code
Next Up: Classes!
In the next module, you'll learn about Classes - Swift's reference types with inheritance, deinitializers, and shared state!
practice.swift
// STRUCTS PRACTICE - PUTTING IT ALL TOGETHER!
// ===== EXERCISE 1: Basic Struct =====
// Create a Book struct with properties and methods
struct Book: Equatable, Hashable {
var title: String
var author: String
var pages: Int
var currentPage: Int = 0
var progress: Double {
return Double(currentPage) / Double(pages) * 100
}
var isFinished: Bool {
return currentPage >= pages
}
mutating func read(pages count: Int) {
currentPage = min(currentPage + count, pages)
}
}
var myBook = Book(title: "Swift Guide", author: "Apple", pages: 300)
myBook.read(pages: 50)
print("Progress: \(myBook.progress)%") // 16.67%
// ===== EXERCISE 2: Protocol Conformance =====
// Create shapes that conform to a protocol
protocol Shape {
var area: Double { get }
var perimeter: Double { get }
func describe() -> String
}
struct Circle: Shape {
var radius: Double
var area: Double {
return Double.pi * radius * radius
}
var perimeter: Double {
return 2 * Double.pi * radius
}
func describe() -> String {
return "Circle with radius \(radius)"
}
}
struct Square: Shape {
var side: Double
var area: Double { return side * side }
var perimeter: Double { return 4 * side }
func describe() -> String {
return "Square with side \(side)"
}
}
let shapes: [Shape] = [Circle(radius: 5), Square(side: 4)]
for shape in shapes {
print("\(shape.describe()): Area = \(shape.area)")
}
// ===== EXERCISE 3: Codable JSON Parsing =====
// Parse API response into structs
struct APIResponse: Codable {
var users: [APIUser]
var total: Int
}
struct APIUser: Codable {
var id: Int
var name: String
var email: String
var isActive: Bool
enum CodingKeys: String, CodingKey {
case id, name, email
case isActive = "is_active"
}
}
let json = """
{
"users": [
{"id": 1, "name": "Alice", "email": "[email protected]", "is_active": true},
{"id": 2, "name": "Bob", "email": "[email protected]", "is_active": false}
],
"total": 2
}
"""
if let data = json.data(using: .utf8),
let response = try? JSONDecoder().decode(APIResponse.self, from: data) {
for user in response.users {
print("\(user.name): \(user.isActive ? "Active" : "Inactive")")
}
}
// ===== EXERCISE 4: Complex Struct with Extensions =====
// Build a shopping cart system
struct Product: Identifiable, Hashable {
let id: UUID
var name: String
var price: Double
init(name: String, price: Double) {
self.id = UUID()
self.name = name
self.price = price
}
}
struct CartItem {
var product: Product
var quantity: Int
var subtotal: Double {
return product.price * Double(quantity)
}
}
struct ShoppingCart {
private(set) var items: [CartItem] = []
var totalItems: Int {
return items.reduce(0) { $0 + $1.quantity }
}
var totalPrice: Double {
return items.reduce(0) { $0 + $1.subtotal }
}
mutating func add(_ product: Product, quantity: Int = 1) {
if let index = items.firstIndex(where: { $0.product.id == product.id }) {
items[index].quantity += quantity
} else {
items.append(CartItem(product: product, quantity: quantity))
}
}
mutating func remove(_ product: Product) {
items.removeAll { $0.product.id == product.id }
}
mutating func clear() {
items.removeAll()
}
}
extension ShoppingCart: CustomStringConvertible {
var description: String {
var result = "Shopping Cart (\(totalItems) items):\n"
for item in items {
result += " - \(item.product.name) x\(item.quantity) = $\(item.subtotal)\n"
}
result += "Total: $\(totalPrice)"
return result
}
}
var cart = ShoppingCart()
let iPhone = Product(name: "iPhone", price: 999)
let airPods = Product(name: "AirPods", price: 199)
cart.add(iPhone)
cart.add(airPods, quantity: 2)
print(cart)
// ===== EXERCISE 5: Value Type Behavior =====
// Demonstrate copy-on-assignment
struct GameState {
var level: Int
var score: Int
var lives: Int
mutating func nextLevel() {
level += 1
score += 100
}
mutating func loseLife() {
lives -= 1
}
}
var currentGame = GameState(level: 1, score: 0, lives: 3)
var savedGame = currentGame // Creates a copy!
currentGame.nextLevel()
currentGame.loseLife()
print("Current: Level \(currentGame.level), Lives \(currentGame.lives)")
print("Saved: Level \(savedGame.level), Lives \(savedGame.lives)")
// Current: Level 2, Lives 2
// Saved: Level 1, Lives 3 (unchanged!)
print("\nš Congratulations! You've completed the Structs module!")Final Challenge!
Create a TodoList app with Todo struct (id, title, isCompleted, priority) and a TodoManager struct with add, remove, toggle, and filter methods!