C
h
i
L
L
u
.
.
.
Apple's Programming Language

The Complete Swift Language Guide

Master Swift — Apple's powerful and expressive language for building iOS, macOS, watchOS, and tvOS applications.

Why Learn Swift?

Swift was introduced by Apple in 2014 and open-sourced in 2015. It was designed to replace Objective-C with a modern, safer, and more expressive syntax. Swift combines the performance of compiled languages with the expressiveness of dynamic languages.

Swift is the primary language for Apple platform development — iOS, macOS, watchOS, and tvOS. It features a strong type system, optionals to eliminate null pointer errors, value semantics with structs, and protocol-oriented programming as a core paradigm.

With SwiftUI, Apple's declarative UI framework, you can build stunning apps across all platforms using a single codebase.

Did you know? Swift is consistently ranked among the fastest-growing languages and is now available on Linux and Windows too.

1. Swift Basics & Variables

Variables, Constants, and Types

Swift uses let for constants and var for variables. Swift infers types but you can also annotate them explicitly. Type safety prevents unexpected type coercions.

// Constants and variables
let appName = "MyApp"        // constant, inferred as String
var score = 0                // variable, inferred as Int
var temperature: Double = 98.6  // explicit type annotation

// String interpolation
let user = "Alice"
let greeting = "Hello, \(user)! Your score is \(score)."
print(greeting)

// Multi-line strings
let message = """
    Welcome to Swift.
    It's type-safe and fast.
    """

// Type conversions
let num = 42
let str = String(num)        // Int to String
let parsed = Int("123")      // String to Int? (optional)

// Tuples
let coordinates = (x: 10.5, y: 20.3)
print("x: \(coordinates.x), y: \(coordinates.y)")

// Control flow
for i in 1...5 {
    if i % 2 == 0 {
        print("\(i) is even")
    } else {
        print("\(i) is odd")
    }
}

var i = 0
while i < 3 {
    print("while: \(i)")
    i += 1
}

2. Collections & Optionals

Arrays, Dictionaries & Optionals

Swift's collections are strongly typed. Optionals (T?) represent values that might be absent — a core safety feature that replaces nil/null crashes with compile-time checks.

// Arrays
var fruits = ["Apple", "Banana", "Mango"]
fruits.append("Orange")
fruits.insert("Grape", at: 1)
print(fruits.count)

for (index, fruit) in fruits.enumerated() {
    print("\(index): \(fruit)")
}

// Dictionaries
var capitals: [String: String] = [
    "France": "Paris",
    "Japan": "Tokyo",
    "India": "New Delhi"
]
capitals["Germany"] = "Berlin"

if let capital = capitals["France"] {
    print("Capital of France: \(capital)")
}

// Optionals
var name: String? = "Alice"
var age: Int? = nil

// Optional binding
if let unwrappedName = name {
    print("Name: \(unwrappedName)")
}

// Nil coalescing
let displayName = name ?? "Anonymous"

// Optional chaining
let uppercased = name?.uppercased()

// Guard let (early exit)
func greet(_ name: String?) {
    guard let name = name else {
        print("No name provided")
        return
    }
    print("Hello, \(name)!")
}

3. Functions & Closures

Functions and Closures

Swift functions have named parameters, default values, and can return multiple values. Closures are self-contained blocks of functionality — used heavily for callbacks and higher-order functions.

// Function with argument labels
func greet(person name: String, from city: String) -> String {
    return "Hello \(name) from \(city)!"
}
let msg = greet(person: "Alice", from: "Paris")

// Default parameters
func createUser(name: String, role: String = "user", active: Bool = true) {
    print("\(name) | \(role) | \(active)")
}
createUser(name: "Bob")
createUser(name: "Carol", role: "admin")

// Returning multiple values with tuple
func minMax(of array: [Int]) -> (min: Int, max: Int)? {
    guard !array.isEmpty else { return nil }
    return (array.min()!, array.max()!)
}

// Closures
let multiply: (Int, Int) -> Int = { x, y in x * y }
print(multiply(3, 4))  // 12

// Higher-order functions
let numbers = [1, 2, 3, 4, 5, 6]
let evens = numbers.filter { $0 % 2 == 0 }
let doubled = numbers.map { $0 * 2 }
let sum = numbers.reduce(0) { $0 + $1 }
print(evens, doubled, sum)

4. Classes, Structs & Protocols

Protocol-Oriented Programming

Swift favors structs over classes for value semantics. Protocols define contracts that types must conform to. Protocol extensions add default implementations.

// Protocol definition
protocol Describable {
    var description: String { get }
    func describe()
}

// Protocol extension with default implementation
extension Describable {
    func describe() {
        print(description)
    }
}

// Struct conforming to protocol
struct Point: Describable {
    let x: Double
    let y: Double
    var description: String {
        "Point(\(x), \(y))"
    }
}

// Class with inheritance
class Vehicle: Describable {
    let make: String
    let year: Int
    init(make: String, year: Int) {
        self.make = make
        self.year = year
    }
    var description: String { "\(year) \(make)" }
}

class ElectricCar: Vehicle {
    let range: Int
    init(make: String, year: Int, range: Int) {
        self.range = range
        super.init(make: make, year: year)
    }
    override var description: String {
        super.description + " (Electric, \(range)mi range)"
    }
}

let point = Point(x: 3.0, y: 4.0)
point.describe()
let car = ElectricCar(make: "Tesla", year: 2024, range: 350)
car.describe()

5. Error Handling

Throwing and Catching Errors

Swift uses do-catch with throwing functions marked with throws. Errors conform to the Error protocol. Swift's error model is explicit and safe.

import Foundation

enum NetworkError: Error {
    case invalidURL
    case noData
    case decodingFailed(String)
}

struct User: Decodable {
    let id: Int
    let name: String
    let email: String
}

// Throwing function
func fetchUser(from urlString: String) throws -> User {
    guard let url = URL(string: urlString) else {
        throw NetworkError.invalidURL
    }
    // Simulate data (in real app, use URLSession)
    let mockJSON = """
    {"id": 1, "name": "Alice", "email": "alice@example.com"}
    """
    guard let data = mockJSON.data(using: .utf8) else {
        throw NetworkError.noData
    }
    do {
        return try JSONDecoder().decode(User.self, from: data)
    } catch {
        throw NetworkError.decodingFailed(error.localizedDescription)
    }
}

// Using do-catch
do {
    let user = try fetchUser(from: "https://api.example.com/user/1")
    print("User: \(user.name)")
} catch NetworkError.invalidURL {
    print("Bad URL")
} catch NetworkError.noData {
    print("No data received")
} catch NetworkError.decodingFailed(let msg) {
    print("Decode error: \(msg)")
}

6. Async/Await & Concurrency

Swift Concurrency Model

Swift 5.5 introduced async/await and actors for structured concurrency. Actors prevent data races by ensuring only one task at a time can access their mutable state.

import Foundation

// Async function
func fetchPosts() async throws -> [String] {
    let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
    let (data, _) = try await URLSession.shared.data(from: url)
    // Decode and return titles
    return ["Post 1", "Post 2", "Post 3"]
}

// Calling async functions
Task {
    do {
        let posts = try await fetchPosts()
        posts.forEach { print($0) }
    } catch {
        print("Error: \(error)")
    }
}

// Parallel async tasks
func loadDashboard() async {
    async let user = fetchUser(from: "https://api.example.com/user/1")
    async let posts = fetchPosts()

    // Both run in parallel
    do {
        let (loadedUser, loadedPosts) = try await (user, posts)
        print("User: \(loadedUser.name), Posts: \(loadedPosts.count)")
    } catch {
        print("Error: \(error)")
    }
}

// Actor for thread-safe state
actor BankAccount {
    private var balance: Double = 0
    func deposit(_ amount: Double) { balance += amount }
    func withdraw(_ amount: Double) -> Bool {
        guard balance >= amount else { return false }
        balance -= amount
        return true
    }
    func getBalance() -> Double { balance }
}

Start Building Apple Apps!

Swift's safety, expressiveness, and performance make it a joy to develop with. Combine it with SwiftUI to build stunning apps across all Apple platforms.

Happy Coding with Swift!