Swift Foundation

Essential framework for dates, files, networking, and more

🏗️ What is Swift Foundation?

Foundation is Apple's fundamental framework providing essential data types, collections, and operating-system services. It includes dates, URLs, file management, networking, and data formatting - the building blocks for most Swift applications.


import Foundation

// Foundation provides essential types
let now = Date()
let url = URL(string: "https://example.com")
let data = "Hello".data(using: .utf8)
let uuid = UUID()

print("Current time: \(now)")
print("UUID: \(uuid.uuidString)")
                                    

Key Foundation Components

📅

Date & Time

Working with dates and time

let now = Date()
let formatter = DateFormatter()
formatter.dateStyle = .medium
🌐

URLs & Networking

URL handling and network requests

let url = URL(string: "https://api.example.com")
let task = URLSession.shared.dataTask(with: url!)
📁

File Management

Reading and writing files

let fileManager = FileManager.default
let documentsPath = fileManager.urls(for: .documentDirectory)
💾

Data & Encoding

Data manipulation and JSON

let jsonData = try JSONEncoder().encode(object)
let decoded = try JSONDecoder().decode(Type.self, from: data)

🔹 Working with Dates

Foundation provides powerful date and time handling:

import Foundation

// Creating dates
let now = Date()
let specificDate = Date(timeIntervalSince1970: 1640995200) // Jan 1, 2022

// Date formatting
let formatter = DateFormatter()
formatter.dateStyle = .full
formatter.timeStyle = .short
let formatted = formatter.string(from: now)

// Custom date format
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let customFormatted = formatter.string(from: now)

// Date components
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day], from: now)
let year = components.year
let month = components.month
let day = components.day

// Date calculations
let tomorrow = calendar.date(byAdding: .day, value: 1, to: now)
let nextWeek = calendar.date(byAdding: .weekOfYear, value: 1, to: now)

// Comparing dates
let isToday = calendar.isDateInToday(now)
let isSameDay = calendar.isDate(now, inSameDayAs: specificDate)

print("Today: \(formatted)")
print("Year: \(year ?? 0), Month: \(month ?? 0), Day: \(day ?? 0)")

🔹 URL and Networking

Handle URLs and make network requests:

import Foundation

// Creating URLs
let urlString = "https://jsonplaceholder.typicode.com/posts/1"
guard let url = URL(string: urlString) else {
    print("Invalid URL")
    return
}

// URL components
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
print("Host: \(components?.host ?? "Unknown")")
print("Path: \(components?.path ?? "Unknown")")

// Simple GET request
func fetchData() async {
    do {
        let (data, response) = try await URLSession.shared.data(from: url)
        
        if let httpResponse = response as? HTTPURLResponse {
            print("Status code: \(httpResponse.statusCode)")
        }
        
        if let jsonString = String(data: data, encoding: .utf8) {
            print("Response: \(jsonString)")
        }
    } catch {
        print("Error: \(error)")
    }
}

// POST request with JSON
func postData() async {
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let postData = ["title": "New Post", "body": "Post content"]
    
    do {
        let jsonData = try JSONSerialization.data(withJSONObject: postData)
        request.httpBody = jsonData
        
        let (data, _) = try await URLSession.shared.data(for: request)
        print("Posted successfully")
    } catch {
        print("Error posting: \(error)")
    }
}

🔹 File Management

Read, write, and manage files on the device:

import Foundation

let fileManager = FileManager.default

// Get common directories
let documentsURL = fileManager.urls(for: .documentDirectory, 
                                   in: .userDomainMask).first!
let desktopURL = fileManager.urls(for: .desktopDirectory, 
                                 in: .userDomainMask).first!

// Create file path
let fileName = "myfile.txt"
let fileURL = documentsURL.appendingPathComponent(fileName)

// Write to file
let content = "Hello, Foundation!"
do {
    try content.write(to: fileURL, atomically: true, encoding: .utf8)
    print("File written successfully")
} catch {
    print("Error writing file: \(error)")
}

// Read from file
do {
    let readContent = try String(contentsOf: fileURL, encoding: .utf8)
    print("File content: \(readContent)")
} catch {
    print("Error reading file: \(error)")
}

// Check if file exists
let fileExists = fileManager.fileExists(atPath: fileURL.path)
print("File exists: \(fileExists)")

// Get file attributes
do {
    let attributes = try fileManager.attributesOfItem(atPath: fileURL.path)
    let fileSize = attributes[.size] as? Int64
    let modificationDate = attributes[.modificationDate] as? Date
    
    print("File size: \(fileSize ?? 0) bytes")
    print("Modified: \(modificationDate ?? Date())")
} catch {
    print("Error getting attributes: \(error)")
}

// Delete file
do {
    try fileManager.removeItem(at: fileURL)
    print("File deleted")
} catch {
    print("Error deleting file: \(error)")
}

🔹 JSON and Data Encoding

Work with JSON and data serialization:

import Foundation

// Define a Codable struct
struct Person: Codable {
    let name: String
    let age: Int
    let email: String
}

struct Company: Codable {
    let name: String
    let employees: [Person]
    let founded: Date
}

// Create sample data
let employees = [
    Person(name: "Alice", age: 30, email: "[email protected]"),
    Person(name: "Bob", age: 25, email: "[email protected]")
]

let company = Company(name: "Tech Corp", 
                     employees: employees, 
                     founded: Date())

// Encode to JSON
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
encoder.outputFormatting = .prettyPrinted

do {
    let jsonData = try encoder.encode(company)
    let jsonString = String(data: jsonData, encoding: .utf8)
    print("JSON:\n\(jsonString ?? "Error")")
    
    // Decode from JSON
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .iso8601
    
    let decodedCompany = try decoder.decode(Company.self, from: jsonData)
    print("\nDecoded company: \(decodedCompany.name)")
    print("Employees: \(decodedCompany.employees.count)")
    
} catch {
    print("Encoding/Decoding error: \(error)")
}

// Working with raw JSON
let jsonString = """
{
    "name": "John",
    "age": 35,
    "active": true
}
"""

if let jsonData = jsonString.data(using: .utf8) {
    do {
        let json = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any]
        let name = json?["name"] as? String
        let age = json?["age"] as? Int
        
        print("Name: \(name ?? "Unknown")")
        print("Age: \(age ?? 0)")
    } catch {
        print("JSON parsing error: \(error)")
    }
}

🔹 UserDefaults and Preferences

Store user preferences and simple data:

import Foundation

let defaults = UserDefaults.standard

// Storing different types
defaults.set("John Doe", forKey: "username")
defaults.set(25, forKey: "userAge")
defaults.set(true, forKey: "isFirstLaunch")
defaults.set(Date(), forKey: "lastLoginDate")

// Storing arrays and dictionaries
let favoriteColors = ["red", "blue", "green"]
defaults.set(favoriteColors, forKey: "favoriteColors")

let userInfo = ["name": "Alice", "role": "admin"]
defaults.set(userInfo, forKey: "userInfo")

// Reading values
let username = defaults.string(forKey: "username") ?? "Unknown"
let userAge = defaults.integer(forKey: "userAge")
let isFirstLaunch = defaults.bool(forKey: "isFirstLaunch")
let lastLogin = defaults.object(forKey: "lastLoginDate") as? Date

// Reading arrays and dictionaries
let colors = defaults.array(forKey: "favoriteColors") as? [String] ?? []
let info = defaults.dictionary(forKey: "userInfo") ?? [:]

print("Username: \(username)")
print("Age: \(userAge)")
print("First launch: \(isFirstLaunch)")
print("Favorite colors: \(colors)")

// Removing values
defaults.removeObject(forKey: "isFirstLaunch")

// Check if key exists
let hasUsername = defaults.object(forKey: "username") != nil

// Synchronize (usually not needed)
defaults.synchronize()

🔹 Foundation Best Practices

Guidelines for effective Foundation usage:

✅ Do:

  • Use Codable for JSON serialization when possible
  • Handle errors properly when working with files and network
  • Use async/await for network requests
  • Cache expensive operations like date formatting
  • Use UserDefaults for simple preferences only

❌ Don't:

  • Store large data in UserDefaults
  • Block the main thread with file operations
  • Ignore URL validation when creating URLs
  • Use force unwrapping with file operations

🧠 Test Your Knowledge

Which Foundation class is used for making network requests?