EMFAD Courses

Module 1: Swift Foundations

Swift Language Essentials

Swift is Apple's modern programming language for iPhone, iPad, Mac, Apple Watch and Apple TV apps. It is designed to be safe, fast and readable. SwiftUI, the framework you will use to build interfaces, leans heavily on Swift features such as structs, closures and protocols, so a solid grasp of the language makes everything else in this course easier.

Constants, variables and types

Use let for constants and var for values that change. Prefer let; the compiler will warn you when a var is never changed. Swift infers types, but every value has exactly one type and Swift will not silently convert between them.

let shopName = "Duka la Amani"     // String
var itemsInBasket = 0               // Int
let price: Double = 349.99          // explicit type
itemsInBasket += 2

let total = Double(itemsInBasket) * price     // convert Int to Double explicitly
print("Total: KES \(total)")                   // string interpolation

String interpolation with \(...) inserts any value into text. The explicit Double(itemsInBasket) conversion is required: Swift refuses to multiply an Int by a Double directly, which prevents subtle rounding bugs.

Functions and closures

Functions use func. Parameters have argument labels that make calls read like sentences. You can use _ to omit a label, and give default values.

func formatPrice(_ amount: Double, currency: String = "KES") -> String {
    let formatted = amount.formatted(.number.precision(.fractionLength(2)))
    return "\(currency) \(formatted)"
}

formatPrice(1250)                     // "KES 1,250.00" (separator depends on locale)
formatPrice(9.5, currency: "USD")     // "USD 9.50"

A closure is a block of code you can pass around, like a function without a name. SwiftUI buttons, list sorting and network completion all use closures. When a closure is the last argument, you can write it after the parentheses, called trailing closure syntax.

let prices = [210.0, 180.0, 390.0, 95.0]
let expensive = prices.filter { $0 > 150 }          // [210, 180, 390]
let withVat = prices.map { $0 * 1.16 }               // hypothetical 16% rate
let sum = prices.reduce(0, +)                        // 875
let sorted = prices.sorted { $0 > $1 }               // descending

$0 and $1 are shorthand names for the closure's first and second parameters.

Structs, enums and protocols

A struct groups related values. Structs are value types: assigning one to another variable makes a copy. SwiftUI views and most app models are structs. A class is a reference type: variables share the same instance. Use structs by default and classes when you need shared, mutable identity.

struct Product {
    let name: String
    var price: Double
    var stock: Int

    var isAvailable: Bool { stock > 0 }               // computed property

    mutating func sell(_ quantity: Int) {
        stock = max(0, stock - quantity)
    }
}

enum PaymentMethod: String, CaseIterable {
    case cash, card, mobileMoney

    var label: String {
        switch self {
        case .cash: return "Cash"
        case .card: return "Card"
        case .mobileMoney: return "Mobile money"
        }
    }
}

An enum lists a fixed set of cases. Swift's switch must handle every case, so if you add a new payment method later, the compiler points to every switch you need to update. A protocol describes requirements a type promises to meet; SwiftUI's View is a protocol, and Identifiable, Codable and Equatable are protocols you will use often.

Worked example: a small sales summary

struct Sale {
    let product: String
    let amount: Double
    let method: PaymentMethod
}

let sales = [
    Sale(product: "Rice 2kg", amount: 520, method: .mobileMoney),
    Sale(product: "Milk 500ml", amount: 390, method: .cash),
    Sale(product: "Bread", amount: 65, method: .mobileMoney)
]

let byMethod = Dictionary(grouping: sales, by: \.method)
for method in PaymentMethod.allCases {
    let total = byMethod[method, default: []].reduce(0) { $0 + $1.amount }
    print("\(method.label): KES \(total)")
}

This groups sales by payment method and prints a total for each, including zero for card. CaseIterable gives allCases, and \.method is a key path pointing at a property. The default subscript [method, default: []] avoids dealing with a missing key.

Common mistakes to avoid

  • Using var when let works. Follow the compiler's warnings.
  • Mixing numeric types. Convert explicitly; do not fight the type system.
  • Forgetting mutating. A struct method that changes properties needs the mutating keyword.
  • Reaching for classes by habit. In Swift and SwiftUI, structs are the normal choice for data.
  • Adding a default case to every switch. It hides missing cases when an enum grows. Handle cases explicitly when you can.

Exercise

Open a new Playground in Xcode (File, New, Playground). Define an enum ExpenseCategory with at least four cases and a label property, and a struct Expense with a title, amount and category. Create eight expenses, then use filter, map, reduce and Dictionary(grouping:by:) to print the total per category and the largest single expense.

Key points

  • Use let by default; Swift never converts numeric types silently
  • Closures with trailing syntax and $0 shorthand are everywhere in SwiftUI
  • Structs are value types and the default choice; classes are reference types
  • Enums with exhaustive switch statements catch missing cases at compile time

Enjoyed this lesson?

The full course has 16 lessons with exercises, a quiz after every module, a final project and a certificate of completion. About 7 hours, USD 49, lifetime access.

Course details