macOS Error Handling Swift Samples

macOS Swift error handling examples including exception catching, logging, and parameter validation

Key Facts

Category
Swift
Items
3
Format Families
audio

Sample Overview

macOS Swift error handling examples including exception catching, logging, and parameter validation This sample set belongs to Swift and can be used to test related workflows inside Elysia Tools.

💻 Exception Catching swift

🟢 simple ⭐⭐

Handle errors using do-catch blocks, try-catch patterns, and custom error types

⏱️ 25 min 🏷️ swift, macos, error
Prerequisites: Basic Swift, Error types
// macOS Swift Exception Catching Examples
// Error handling with do-catch, throws, and custom errors

import Foundation

// 1. Define Custom Error Types
enum NetworkError: Error, LocalizedError {
    case invalidURL
    case connectionFailed
    case timeout
    case serverError(code: Int)

    var errorDescription: String? {
        switch self {
        case .invalidURL:
            return "The provided URL is invalid"
        case .connectionFailed:
            return "Failed to establish network connection"
        case .timeout:
            return "Request timed out"
        case .serverError(let code):
            return "Server returned error code: \(code)"
        }
    }
}

enum ValidationError: Error {
    case emptyInput
    case invalidFormat
    case outOfRange(min: Int, max: Int, value: Int)
    case tooShort(length: Int, minLength: Int)

    var localizedDescription: String {
        switch self {
        case .emptyInput:
            return "Input cannot be empty"
        case .invalidFormat:
            return "Input format is invalid"
        case .outOfRange(let min, let max, let value):
            return "Value \(value) is out of range [\(min), \(max)]"
        case .tooShort(let length, let minLength):
            return "Input length \(length) is too short (minimum: \(minLength))"
        }
    }
}

// 2. Basic do-catch Error Handling
class BasicErrorHandling {

    func divide(_ a: Int, by b: Int) throws -> Double {
        guard b != 0 else {
            throw NSError(domain: "MathError", code: 1, userInfo: [
                NSLocalizedDescriptionKey: "Division by zero is not allowed"
            ])
        }
        return Double(a) / Double(b)
    }

    func demonstrateBasicCatch() {
        print("\n--- Basic do-catch Error Handling ---")

        do {
            let result = try divide(10, by: 2)
            print("10 / 2 = \(result)")
        } catch {
            print("Error: \(error.localizedDescription)")
        }

        // Error case
        do {
            let result = try divide(10, by: 0)
            print("Result: \(result)")
        } catch {
            print("Caught error: \(error.localizedDescription)")
        }
    }
}

// 3. Multiple Catch Blocks
class MultipleCatchBlocks {

    func processOperation(value: Int) throws -> String {
        if value < 0 {
            throw NetworkError.invalidURL
        } else if value == 0 {
            throw ValidationError.emptyInput
        }
        return "Success: \(value)"
    }

    func demonstrateMultipleCatches() {
        print("\n--- Multiple Catch Blocks ---")

        let values = [-1, 0, 5]

        for value in values {
            do {
                let result = try processOperation(value: value)
                print(result)
            } catch let error as NetworkError {
                print("Network error: \(error.errorDescription ?? "Unknown")")
            } catch let error as ValidationError {
                print("Validation error: \(error.localizedDescription)")
            } catch {
                print("Generic error: \(error.localizedDescription)")
            }
        }
    }
}

// 4. try? - Convert to Optional
class OptionalTry {

    func riskyOperation(success: Bool) throws -> String {
        if success {
            return "Operation succeeded"
        } else {
            throw NSError(domain: "Error", code: 1)
        }
    }

    func demonstrateOptionalTry() {
        print("\n--- try? - Convert to Optional ---")

        // Success case - returns Optional("Operation succeeded")
        let result1 = try? riskyOperation(success: true)
        print("Result 1: \(result1 ?? "nil")")

        // Failure case - returns nil instead of throwing
        let result2 = try? riskyOperation(success: false)
        print("Result 2: \(result2?.description ?? "nil")")

        // Chaining with nil coalescing
        let finalResult = (try? riskyOperation(success: false)) ?? "Default value"
        print("Final result: \(finalResult)")
    }
}

// 5. try! - Force Unwrap
class ForceTry {

    func forceUnwrapDemo() {
        print("\n--- try! - Force Unwrap ---")

        // This works because operation succeeds
        let result1 = try! riskyOperation(success: true)
        print("Force unwrap success: \(result1)")

        // This would crash because operation fails
        do {
            // let result2 = try! riskyOperation(success: false)  // CRASH!
            // print("Never reached")
        }

        print("Use try! only when you're certain the operation won't fail")
    }

    private func riskyOperation(success: Bool) throws -> String {
        return success ? "Success" : "Failure"
    }
}

// 6. defer Statement
class DeferExample {

    func processFile(path: String) throws -> String {
        print("\n--- Defer Statement ---")
        print("Opening file: \(path)")

        // defer will execute when scope exits
        defer {
            print("Closing file: \(path)")
        }

        // Simulate processing
        print("Processing file...")

        if path.isEmpty {
            throw ValidationError.emptyInput
        }

        return "File processed successfully"
    }

    func demonstrateDefer() {
        do {
            let result = try processFile(path: "/path/to/file.txt")
            print(result)
        } catch {
            print("Error: \(error)")
        }

        // Error case - defer still executes
        do {
            let result = try processFile(path: "")
            print(result)
        } catch {
            print("Error caught: \(error)")
        }
    }

    // Multiple defer blocks (LIFO order)
    func multipleDefer() {
        print("\n--- Multiple Defer Blocks ---")

        defer { print("Defer 1") }
        defer { print("Defer 2") }
        defer { print("Defer 3") }

        print("Main code")
    }
}

// 7. Rethrowing Functions
class RethrowingExample {

    func transform<T>(_ value: T, using transform: (T) throws -> String) rethrows -> String {
        print("\n--- Rethrowing Function ---")
        return try transform(value)
    }

    func demonstrateRethrow() {
        do {
            let result = try transform(42) { value in
                if value < 0 {
                    throw ValidationError.invalidFormat
                }
                return "Transformed: \(value)"
            }
            print(result)
        } catch {
            print("Error: \(error)")
        }
    }
}

// 8. Error Propagation
class ErrorPropagation {

    func step1() throws -> String {
        print("Step 1")
        return "Step1"
    }

    func step2(input: String) throws -> String {
        print("Step 2 with: \(input)")
        if input.isEmpty {
            throw ValidationError.emptyInput
        }
        return input + " -> Step2"
    }

    func step3(input: String) throws -> String {
        print("Step 3 with: \(input)")
        return input + " -> Step3"
    }

    func executePipeline() throws -> String {
        print("\n--- Error Propagation ---")

        let result1 = try step1()
        let result2 = try step2(input: result1)
        let result3 = try step3(input: result2)

        return result3
    }

    func demonstratePropagation() {
        do {
            let result = try executePipeline()
            print("Pipeline result: \(result)")
        } catch {
            print("Pipeline failed: \(error)")
        }
    }
}

// 9. Result Type for Error Handling
class ResultTypeExample {

    func divideResult(_ a: Int, by b: Int) -> Result<Double, Error> {
        guard b != 0 else {
            return .failure(NSError(domain: "MathError", code: 1, userInfo: [
                NSLocalizedDescriptionKey: "Division by zero"
            ]))
        }
        return .success(Double(a) / Double(b))
    }

    func demonstrateResult() {
        print("\n--- Result Type ---")

        let result1 = divideResult(10, by: 2)

        switch result1 {
        case .success(let value):
            print("10 / 2 = \(value)")
        case .failure(let error):
            print("Error: \(error)")
        }

        // Error case
        let result2 = divideResult(10, by: 0)

        switch result2 {
        case .success(let value):
            print("Result: \(value)")
        case .failure(let error):
            print("Error: \(error.localizedDescription)")
        }

        // Using get() method
        if let value = try? divideResult(20, by: 4).get() {
            print("Direct get: \(value)")
        }
    }
}

// 10. Comprehensive Error Handler
class ComprehensiveErrorHandler {

    enum AppError: Error {
        case network(NetworkError)
        case validation(ValidationError)
        case unknown(Error)

        var localizedDescription: String {
            switch self {
            case .network(let error):
                return "Network: \(error.errorDescription ?? "Unknown")"
            case .validation(let error):
                return "Validation: \(error.localizedDescription)"
            case .unknown(let error):
                return "Unknown: \(error.localizedDescription)"
            }
        }
    }

    func handleOperation(operation: () throws -> Void) {
        print("\n--- Comprehensive Error Handling ---")

        do {
            try operation()
            print("Operation completed successfully")
        } catch let error as NetworkError {
            let appError = AppError.network(error)
            handleAppError(appError)
        } catch let error as ValidationError {
            let appError = AppError.validation(error)
            handleAppError(appError)
        } catch {
            let appError = AppError.unknown(error)
            handleAppError(appError)
        }
    }

    private func handleAppError(_ error: AppError) {
        print("Error occurred: \(error.localizedDescription)")

        switch error {
        case .network:
            print("Suggested action: Check your internet connection")
        case .validation:
            print("Suggested action: Please check your input")
        case .unknown:
            print("Suggested action: Please try again later")
        }
    }

    func demonstrateComprehensive() {
        // Success case
        handleOperation {
            print("Executing operation...")
        }

        // Network error
        handleOperation {
            throw NetworkError.connectionFailed
        }

        // Validation error
        handleOperation {
            throw ValidationError.invalidFormat
        }
    }
}

// 11. Async Error Handling
class AsyncErrorHandling {

    func fetchData() async throws -> String {
        print("\n--- Async Error Handling ---")

        // Simulate async operation
        try await Task.sleep(nanoseconds: 100_000_000) // 0.1 seconds

        let success = true

        if success {
            return "Data fetched successfully"
        } else {
            throw NetworkError.timeout
        }
    }

    func demonstrateAsync() async {
        do {
            let result = try await fetchData()
            print(result)
        } catch {
            print("Async error: \(error)")
        }
    }
}

// 12. Error Logging with Context
class ErrorWithContext {

    struct ErrorContext {
        let operation: String
        let timestamp: Date
        let additionalInfo: [String: Any]

        var description: String {
            let info = additionalInfo.map { "\($0.key): \($0.value)" }.joined(separator: ", ")
            return "[\(timestamp)] Operation '\(operation)' failed. Info: \(info)"
        }
    }

    enum ContextualError: Error {
        case operationFailed(context: ErrorContext)
        case validationFailed(context: ErrorContext)

        var localizedDescription: String {
            switch self {
            case .operationFailed(let context):
                return "Operation failed - " + context.description
            case .validationFailed(let context):
                return "Validation failed - " + context.description
            }
        }
    }

    func performOperation(userId: String, value: Int) throws {
        print("\n--- Error with Context ---")

        guard !userId.isEmpty else {
            let context = ErrorContext(
                operation: "performOperation",
                timestamp: Date(),
                additionalInfo: ["userId": userId, "reason": "empty"]
            )
            throw ContextualError.validationFailed(context: context)
        }

        guard value > 0 else {
            let context = ErrorContext(
                operation: "performOperation",
                timestamp: Date(),
                additionalInfo: ["userId": userId, "value": value]
            )
            throw ContextualError.operationFailed(context: context)
        }

        print("Operation succeeded for user \(userId) with value \(value)")
    }

    func demonstrateContext() {
        do {
            try performOperation(userId: "user123", value: 10)
        } catch let error as ContextualError {
            print("Error: \(error.localizedDescription)")
        } catch {
            print("Unexpected error: \(error.localizedDescription)")
        }

        do {
            try performOperation(userId: "", value: 10)
        } catch let error as ContextualError {
            print("Error: \(error.localizedDescription)")
        } catch {
            print("Unexpected error: \(error.localizedDescription)")
        }
    }
}

// Main demonstration
func demonstrateExceptionCatching() {
    print("=== macOS Swift Exception Catching Examples ===")

    // 1. Basic error handling
    let basic = BasicErrorHandling()
    basic.demonstrateBasicCatch()

    // 2. Multiple catch blocks
    let multiCatch = MultipleCatchBlocks()
    multiCatch.demonstrateMultipleCatches()

    // 3. Optional try
    let optionalTry = OptionalTry()
    optionalTry.demonstrateOptionalTry()

    // 4. Force try
    let forceTry = ForceTry()
    forceTry.forceUnwrapDemo()

    // 5. Defer
    let deferExample = DeferExample()
    deferExample.demonstrateDefer()
    deferExample.multipleDefer()

    // 6. Rethrowing
    let rethrow = RethrowingExample()
    rethrow.demonstrateRethrow()

    // 7. Error propagation
    let propagation = ErrorPropagation()
    propagation.demonstratePropagation()

    // 8. Result type
    let resultType = ResultTypeExample()
    resultType.demonstrateResult()

    // 9. Comprehensive handler
    let comprehensive = ComprehensiveErrorHandler()
    comprehensive.demonstrateComprehensive()

    // 10. Error with context
    let context = ErrorWithContext()
    context.demonstrateContext()

    print("\n=== All Exception Catching Examples Completed ===")
}

// Run demonstration
demonstrateExceptionCatching()

💻 Logging swift

🟡 intermediate ⭐⭐⭐

Implement comprehensive logging system with file output, log levels, and rotation

⏱️ 30 min 🏷️ swift, macos, logging
Prerequisites: Intermediate Swift, File I/O
// macOS Swift Logging Examples
// Comprehensive logging with file output, levels, and rotation

import Foundation
import OSLog

// 1. Simple Print Logging
class SimpleLogger {

    func log(message: String) {
        print("[LOG] \(message)")
    }

    func logInfo(message: String) {
        print("[INFO] \(message)")
    }

    func logWarning(message: String) {
        print("[WARNING] \(message)")
    }

    func logError(message: String) {
        print("[ERROR] \(message)")
    }

    func demonstrateSimpleLogging() {
        print("\n--- Simple Print Logging ---")
        logInfo(message: "Application started")
        logWarning(message: "This is a warning")
        logError(message: "An error occurred")
        log(message: "Custom log message")
    }
}

// 2. Custom Logger with Levels
enum LogLevel: String, Comparable {
    case debug = "DEBUG"
    case info = "INFO"
    case warning = "WARNING"
    case error = "ERROR"
    case critical = "CRITICAL"

    static func < (lhs: LogLevel, rhs: LogLevel) -> Bool {
        let order: [LogLevel] = [.debug, .info, .warning, .error, .critical]
        return order.firstIndex(of: lhs)! < order.firstIndex(of: rhs)!
    }
}

struct LogEntry {
    let timestamp: Date
    let level: LogLevel
    let message: String
    let file: String
    let function: String
    let line: Int

    var formatted: String {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
        let timeString = formatter.string(from: timestamp)

        let fileName = URL(fileURLWithPath: file).lastPathComponent

        return "[\(timeString)] [\(level.rawValue)] [\(fileName):\(line)] \(function): \(message)"
    }
}

class CustomLogger {
    static let shared = CustomLogger()

    private var logs: [LogEntry] = []
    private var minimumLevel: LogLevel = .debug
    private let lock = NSLock()

    private init() {}

    func setMinimumLevel(_ level: LogLevel) {
        lock.lock()
        defer { lock.unlock() }
        minimumLevel = level
    }

    func log(_ level: LogLevel, message: String, file: String = #file, function: String = #function, line: Int = #line) {
        guard level >= minimumLevel else { return }

        let entry = LogEntry(
            timestamp: Date(),
            level: level,
            message: message,
            file: file,
            function: function,
            line: line
        )

        lock.lock()
        logs.append(entry)
        lock.unlock()

        print(entry.formatted)
    }

    func debug(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
        log(.debug, message: message, file: file, function: function, line: line)
    }

    func info(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
        log(.info, message: message, file: file, function: function, line: line)
    }

    func warning(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
        log(.warning, message: message, file: file, function: function, line: line)
    }

    func error(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
        log(.error, message: message, file: file, function: function, line: line)
    }

    func critical(_ message: String, file: String = #file, function: String = #function, line: Int = #line) {
        log(.critical, message: message, file: file, function: function, line: line)
    }

    func getLogs() -> [LogEntry] {
        lock.lock()
        defer { lock.unlock() }
        return logs
    }

    func clearLogs() {
        lock.lock()
        defer { lock.unlock() }
        logs.removeAll()
    }
}

// 3. File Logger
class FileLogger {
    private let fileURL: URL
    private let fileHandle: FileHandle?
    private let dateFormatter: DateFormatter

    init?(filename: String = "app.log") {
        let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        fileURL = documentsPath.appendingPathComponent(filename)

        // Create file if it doesn't exist
        if !FileManager.default.fileExists(atPath: fileURL.path) {
            FileManager.default.createFile(atPath: fileURL.path, contents: nil, attributes: nil)
        }

        // Open file handle
        do {
            fileHandle = try FileHandle(forWritingTo: fileURL)
            fileHandle?.seekToEndOfFile()
        } catch {
            print("Failed to open log file: \(error)")
            return nil
        }

        dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
    }

    deinit {
        fileHandle?.closeFile()
    }

    func log(level: LogLevel, message: String) {
        let timestamp = dateFormatter.string(from: Date())
        let logLine = "[\(timestamp)] [\(level.rawValue)] \(message)\n"

        if let data = logLine.data(using: .utf8) {
            fileHandle?.write(data)
        }

        // Also print to console
        print(logLine, terminator: "")
    }

    func readLogEntries(limit: Int = 100) -> [String] {
        guard let content = try? String(contentsOf: fileURL) else {
            return []
        }

        let lines = content.components(separatedBy: .newlines)
        return Array(lines.suffix(limit))
    }

    func clearLogFile() {
        try? "".write(to: fileURL, atomically: true, encoding: .utf8)
        print("Log file cleared")
    }
}

// 4. Rotating File Logger
class RotatingFileLogger {
    private let baseURL: URL
    private let maxFileSize: Int64
    private let maxLogFiles: Int
    private var currentFileLogger: FileLogger?

    init(baseFilename: String = "app", maxFileSize: Int64 = 1024 * 1024, maxLogFiles: Int = 5) {
        let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        baseURL = documentsPath
        self.maxFileSize = maxFileSize
        self.maxLogFiles = maxLogFiles

        openNewLogFile()
    }

    private func openNewLogFile() {
        let timestamp = DateFormatter().string(from: Date()).replacingOccurrences(of: " ", with: "_")
        let filename = "app_\(timestamp).log"

        currentFileLogger = FileLogger(filename: filename)
        print("Opened new log file: \(filename)")
    }

    private func rotateLogFiles() {
        let fileManager = FileManager.default

        // Get existing log files
        do {
            let files = try fileManager.contentsOfDirectory(at: baseURL, includingPropertiesForKeys: [.fileSizeKey], options: [])

            let logFiles = files.filter { $0.pathExtension == "log" }
                .sorted { $0.lastPathComponent > $1.lastPathComponent }

            // Remove old files if exceeding limit
            if logFiles.count > maxLogFiles {
                for i in maxLogFiles..<logFiles.count {
                    try? fileManager.removeItem(at: logFiles[i])
                    print("Removed old log file: \(logFiles[i].lastPathComponent)")
                }
            }
        } catch {
            print("Error rotating log files: \(error)")
        }
    }

    func log(level: LogLevel, message: String) {
        // Check if current file size exceeds limit
        if let fileURL = currentFileLogger?.fileURL,
           let attributes = try? FileManager.default.attributesOfItem(atPath: fileURL.path),
           let fileSize = attributes[.size] as? Int64,
           fileSize > maxFileSize {

            currentFileLogger = nil
            rotateLogFiles()
            openNewLogFile()
        }

        currentFileLogger?.log(level: level, message: message)
    }
}

// 5. Unified Logging (OSLog)
class OSLogLogger {
    private let logger = Logger(subsystem: "com.example.app", category: "General")

    init() {
        print("\n--- OSLog / Unified Logging ---")
    }

    func logDebug(_ message: String) {
        logger.debug("\(message)")
    }

    func logInfo(_ message: String) {
        logger.info("\(message)")
    }

    func logError(_ message: String) {
        logger.error("\(message)")
    }

    func logFault(_ message: String) {
        logger.fault("\(message)")
    }

    // With privacy
    func logWithPrivacy(_ message: String, userId: String) {
        logger.log("User \(privacy: .public(userId)) performed action: \(message)")
    }

    func demonstrateOSLog() {
        logDebug("This is a debug message")
        logInfo("Application started")
        logError("An error occurred")
        logFault("Critical failure!")

        logWithPrivacy("Logged in", userId: "user123")
        print("Check Console.app for OSLog messages")
    }
}

// 6. Structured Logging
struct StructuredLogEntry: Encodable {
    let timestamp: Date
    let level: String
    let message: String
    let context: [String: Any]

    enum CodingKeys: String, CodingKey {
        case timestamp, level, message, context
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(ISO8601DateFormatter().string(from: timestamp), forKey: .timestamp)
        try container.encode(level, forKey: .level)
        try container.encode(message, forKey: .message)

        let contextData = try JSONSerialization.data(withJSONObject: context)
        try container.encode(String(data: contextData, encoding: .utf8), forKey: .context)
    }
}

class StructuredLogger {
    private let entries: [StructuredLogEntry] = []
    private let lock = NSLock()

    func log(level: LogLevel, message: String, context: [String: Any] = [:]) {
        var logContext = context
        logContext["thread"] = Thread.current.isMainThread ? "main" : "background"
        logContext["processId"] = ProcessInfo.processInfo.processIdentifier

        let entry = StructuredLogEntry(
            timestamp: Date(),
            level: level.rawValue,
            message: message,
            context: logContext
        )

        lock.lock()
        defer { lock.unlock() }

        // In real implementation, would store entry
        print("Structured: \(entry)")
    }

    func logRequest(endpoint: String, statusCode: Int, duration: TimeInterval) {
        log(level: .info, message: "API Request completed", context: [
            "endpoint": endpoint,
            "statusCode": statusCode,
            "duration_ms": duration * 1000
        ])
    }
}

// 7. Performance Logger
class PerformanceLogger {
    private var startTimes: [String: Date] = [:]
    private let logger = CustomLogger.shared

    func startOperation(_ name: String) {
        startTimes[name] = Date()
        logger.debug("Operation '\(name)' started")
    }

    func endOperation(_ name: String) {
        guard let startTime = startTimes[name] else {
            logger.warning("Operation '\(name)' was not started")
            return
        }

        let duration = Date().timeIntervalSince(startTime)
        startTimes.removeValue(forKey: name)

        logger.info("Operation '\(name)' completed in \(String(format: "%.3f", duration))s")
    }

    func measure<T>(_ name: String, operation: () -> T) -> T {
        startOperation(name)
        let result = operation()
        endOperation(name)
        return result
    }

    func measureAsync<T>(_ name: String, operation: () async throws -> T) async rethrows -> T {
        startOperation(name)
        let result = try await operation()
        endOperation(name)
        return result
    }
}

// 8. Error Logger
class ErrorLogger {
    private let logger = CustomLogger.shared
    private let fileLogger: FileLogger?

    init() {
        fileLogger = FileLogger(filename: "errors.log")
    }

    func logError(_ error: Error, context: [String: Any] = [:], file: String = #file, function: String = #function, line: Int = #line) {
        let fileName = URL(fileURLWithPath: file).lastPathComponent

        var message = "Error in \(fileName):\(line) \(function): \(error.localizedDescription)"
        if !context.isEmpty {
            let contextString = context.map { "\($0.key)=\($0.value)" }.joined(separator: ", ")
            message += " | Context: \(contextString)"
        }

        logger.error(message)
        fileLogger?.log(level: .error, message: message)
    }

    func logException(_ exception: NSException) {
        let message = "Exception: \(exception.name) - \(exception.reason ?? "No reason")"
        logger.critical(message)
        fileLogger?.log(level: .critical, message: message)

        if let stackTrace = exception.callStackSymbols.joined(separator: "\n") as String? {
            fileLogger?.log(level: .critical, message: "Stack trace:\n\(stackTrace)")
        }
    }
}

// 9. Network Request Logger
class NetworkLogger {
    private let logger = CustomLogger.shared

    func logRequest(url: String, method: String, headers: [String: String] = [:], body: Data? = nil) {
        logger.info("API Request: \(method) \(url)")

        if !headers.isEmpty {
            logger.debug("Headers: \(headers)")
        }

        if let body = body, let jsonString = try? JSONSerialization.jsonObject(with: body, options: []) {
            logger.debug("Body: \(jsonString)")
        }
    }

    func logResponse(url: String, statusCode: Int, headers: [String: String] = [:], body: Data? = nil, duration: TimeInterval) {
        let statusLevel = statusCode < 400 ? LogLevel.info : LogLevel.error
        logger.log(statusLevel, message: "API Response: \(url) - Status: \(statusCode) - Duration: \(String(format: "%.3f", duration))s")

        if let body = body, let jsonString = try? JSONSerialization.jsonObject(with: body, options: []) {
            logger.debug("Response body: \(jsonString)")
        }
    }

    func logNetworkError(url: String, error: Error) {
        logger.error("API Error: \(url) - \(error.localizedDescription)")
    }
}

// 10. Log Aggregation and Filtering
class LogAggregator {
    private var loggers: [CustomLogger] = []
    private let fileLogger: FileLogger

    init() {
        fileLogger = FileLogger(filename: "aggregated.log")!
    }

    func addLogger(_ logger: CustomLogger) {
        loggers.append(logger)
    }

    func broadcast(level: LogLevel, message: String) {
        for logger in loggers {
            logger.log(level, message: message)
        }
        fileLogger.log(level: level, message: message)
    }

    func getLogsByLevel(_ level: LogLevel) -> [LogEntry] {
        var filtered: [LogEntry] = []

        for logger in loggers {
            filtered.append(contentsOf: logger.getLogs().filter { $0.level == level })
        }

        return filtered
    }
}

// Main demonstration
func demonstrateLogging() {
    print("=== macOS Swift Logging Examples ===")

    // 1. Simple logging
    let simple = SimpleLogger()
    simple.demonstrateSimpleLogging()

    // 2. Custom logger
    print("\n--- Custom Logger with Levels ---")
    let logger = CustomLogger.shared
    logger.setMinimumLevel(.info)
    logger.debug("This won't be logged")
    logger.info("Application starting...")
    logger.warning("Configuration file not found, using defaults")
    logger.error("Failed to connect to database")
    logger.critical("System out of memory!")

    // 3. File logger
    print("\n--- File Logger ---")
    if let fileLogger = FileLogger(filename: "demo.log") {
        fileLogger.log(level: .info, message: "Application started")
        fileLogger.log(level: .warning, message: "This is a warning")
        fileLogger.log(level: .error, message: "An error occurred")

        print("\nLog file entries:")
        let entries = fileLogger.readLogEntries()
        entries.forEach { print($0) }
    }

    // 4. OSLog
    let osLog = OSLogLogger()
    osLog.demonstrateOSLog()

    // 5. Performance logger
    print("\n--- Performance Logger ---")
    let perfLogger = PerformanceLogger()

    let result = perfLogger.measure("calculation") {
        var sum = 0
        for i in 1...1000 { sum += i }
        return sum
    }
    print("Calculation result: \(result)")

    // 6. Error logger
    print("\n--- Error Logger ---")
    let errorLogger = ErrorLogger()
    do {
        throw NSError(domain: "Test", code: 1, userInfo: [NSLocalizedDescriptionKey: "Test error"])
    } catch {
        errorLogger.logError(error, context: ["userId": "123", "action": "login"])
    }

    // 7. Network logger
    print("\n--- Network Logger ---")
    let networkLogger = NetworkLogger()
    networkLogger.logRequest(url: "https://api.example.com/users", method: "GET")
    networkLogger.logResponse(url: "https://api.example.com/users", statusCode: 200, duration: 0.234)
    networkLogger.logNetworkError(url: "https://api.example.com/users", error: NSError(domain: "Network", code: -1009))

    // 8. Structured logger
    print("\n--- Structured Logger ---")
    let structLogger = StructuredLogger()
    structLogger.logRequest(endpoint: "/api/users", statusCode: 200, duration: 0.123)

    print("\n=== All Logging Examples Completed ===")
}

// Run demonstration
demonstrateLogging()

💻 Parameter Validation swift

🟡 intermediate ⭐⭐⭐

Validate function parameters with predicates, custom validators, and error messages

⏱️ 30 min 🏷️ swift, macos, validation
Prerequisites: Intermediate Swift, Generics
// macOS Swift Parameter Validation Examples
// Comprehensive parameter validation with predicates and custom validators

import Foundation

// 1. Basic Validation Functions
struct Validator {

    static func validateNotEmpty(_ value: String, fieldName: String = "Value") throws {
        guard !value.isEmpty else {
            throw ValidationError.emptyInput
        }
    }

    static func validatePositive(_ value: Int, fieldName: String = "Value") throws {
        guard value > 0 else {
            throw ValidationError.outOfRange(min: 1, max: Int.max, value: value)
        }
    }

    static func validateRange(_ value: Int, min: Int, max: Int, fieldName: String = "Value") throws {
        guard value >= min && value <= max else {
            throw ValidationError.outOfRange(min: min, max: max, value: value)
        }
    }

    static func validateMinLength(_ value: String, minLength: Int, fieldName: String = "Value") throws {
        guard value.count >= minLength else {
            throw ValidationError.tooShort(length: value.count, minLength: minLength)
        }
    }

    static func validateEmail(_ email: String) throws {
        let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
        let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegex)

        guard emailPredicate.evaluate(with: email) else {
            throw ValidationError.invalidFormat
        }
    }

    static func validateURL(_ url: String) throws {
        guard let _ = URL(string: url), url.hasPrefix("http") else {
            throw ValidationError.invalidFormat
        }
    }

    static func validatePhoneNumber(_ phone: String) throws {
        let phoneRegex = "^[+]{0,1}[0-9]{6,14}$"
        let phonePredicate = NSPredicate(format: "SELF MATCHES %@", phoneRegex)

        guard phonePredicate.evaluate(with: phone) else {
            throw ValidationError.invalidFormat
        }
    }
}

// 2. Validation Result
enum ValidationResult {
    case valid
    case invalid(reason: String)

    var isValid: Bool {
        if case .valid = self { return true }
        return false
    }

    var reason: String? {
        if case .invalid(let reason) = self { return reason }
        return nil
    }
}

// 3. Generic Validator
struct GenericValidator<T> {
    let validations: [(T) -> ValidationResult]

    init(@ValidationBuilder validations: () -> [(T) -> ValidationResult]) {
        self.validations = validations()
    }

    func validate(_ value: T) -> ValidationResult {
        for validation in validations {
            let result = validation(value)
            if case .invalid = result {
                return result
            }
        }
        return .valid
    }
}

@resultBuilder
struct ValidationBuilder {
    static func buildBlock(_ components: [(Any) -> ValidationResult]...) -> [(Any) -> ValidationResult] {
        components.flatMap { $0 }
    }

    static func buildExpression(_ expression: (Any) -> ValidationResult) -> [(Any) -> ValidationResult] {
        [expression]
    }
}

// 4. Common Validators
extension GenericValidator {

    static func notEmpty(fieldName: String = "Value") -> GenericValidator<String> {
        GenericValidator {
            [
                { value in
                    value.isEmpty ? .invalid(reason: "\(fieldName) cannot be empty") : .valid
                }
            ]
        }
    }

    static func minLength(_ length: Int, fieldName: String = "Value") -> GenericValidator<String> {
        GenericValidator {
            [
                { value in
                    value.count < length ? .invalid(reason: "\(fieldName) must be at least \(length) characters") : .valid
                }
            ]
        }
    }

    static func maxLength(_ length: Int, fieldName: String = "Value") -> GenericValidator<String> {
        GenericValidator {
            [
                { value in
                    value.count > length ? .invalid(reason: "\(fieldName) must not exceed \(length) characters") : .valid
                }
            ]
        }
    }

    static func range(min: Int, max: Int, fieldName: String = "Value") -> GenericValidator<Int> {
        GenericValidator {
            [
                { value in
                    value < min || value > max ? .invalid(reason: "\(fieldName) must be between \(min) and \(max)") : .valid
                    }
            ]
        }
    }

    static func positive(fieldName: String = "Value") -> GenericValidator<Int> {
        GenericValidator {
            [
                { value in
                    value <= 0 ? .invalid(reason: "\(fieldName) must be positive") : .valid
                }
            ]
        }
    }

    static func email() -> GenericValidator<String> {
        GenericValidator {
            [
                { value in
                    let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
                    let predicate = NSPredicate(format: "SELF MATCHES %@", emailRegex)
                    predicate.evaluate(with: value) ? .valid : .invalid(reason: "Invalid email format")
                }
            ]
        }
    }

    static func url() -> GenericValidator<String> {
        GenericValidator {
            [
                { value in
                    guard let url = URL(string: value) else {
                        return .invalid(reason: "Invalid URL format")
                    }
                    return url.scheme == "http" || url.scheme == "https" ? .valid : .invalid(reason: "URL must start with http:// or https://")
                }
            ]
        }
    }

    static func matches(_ regex: String, fieldName: String = "Value") -> GenericValidator<String> {
        GenericValidator {
            [
                { value in
                    let predicate = NSPredicate(format: "SELF MATCHES %@", regex)
                    predicate.evaluate(with: value) ? .valid : .invalid(reason: "\(fieldName) format is invalid")
                }
            ]
        }
    }

    static func custom(_ predicate: @escaping (T) -> Bool, errorReason: String) -> GenericValidator<T> {
        GenericValidator {
            [
                { value in
                    predicate(value) ? .valid : .invalid(reason: errorReason)
                }
            ]
        }
    }
}

// 5. Combining Validators
class CombinedValidator {

    func validateUsername(_ username: String) -> ValidationResult {
        let validator = GenericValidator
            .notEmpty(fieldName: "Username")
            .minLength(3, fieldName: "Username")
            .maxLength(20, fieldName: "Username")
            .matches("^[a-zA-Z0-9_]+$", fieldName: "Username")

        return validator.validate(username)
    }

    func validatePassword(_ password: String) -> ValidationResult {
        let hasUpperCase = NSPredicate(format: "SELF MATCHES %@", ".*[A-Z]+.*")
        let hasLowerCase = NSPredicate(format: "SELF MATCHES %@", ".*[a-z]+.*")
        let hasNumber = NSPredicate(format: "SELF MATCHES %@", ".*[0-9]+.*")
        let hasSpecial = NSPredicate(format: "SELF MATCHES %@", ".*[!@#$%^&*()_+]+.*")

        let checks = [
            hasUpperCase.evaluate(with: password),
            hasLowerCase.evaluate(with: password),
            hasNumber.evaluate(with: password),
            hasSpecial.evaluate(with: password)
        ]

        if password.count < 8 {
            return .invalid(reason: "Password must be at least 8 characters")
        }

        if !checks.allSatisfy({ $0 }) {
            return .invalid(reason: "Password must contain uppercase, lowercase, number, and special character")
        }

        return .valid
    }

    func validateAge(_ age: Int) -> ValidationResult {
        let validator = GenericValidator
            .range(min: 0, max: 150, fieldName: "Age")

        return validator.validate(age)
    }

    func validateUser(name: String, email: String, age: Int) -> [String] {
        var errors: [String] = []

        switch validateUsername(name) {
        case .invalid(let reason): errors.append(reason)
        default: break
        }

        switch GenericValidator.email().validate(email) {
        case .invalid(let reason): errors.append(reason)
        default: break
        }

        switch validateAge(age) {
        case .invalid(let reason): errors.append(reason)
        default: break
        }

        return errors
    }
}

// 6. Property Wrapper Validation
@propertyWrapper
struct ValidatedString {
    private var value: String
    private let validator: (String) -> ValidationResult

    var wrappedValue: String {
        get { value }
        set {
            let result = validator(newValue)
            if case .valid = result {
                value = newValue
            } else {
                print("Validation error: \(result.reason ?? "Unknown")")
            }
        }
    }

    init(wrappedValue: String, validator: @escaping (String) -> ValidationResult) {
        self.value = wrappedValue
        self.validator = validator
    }
}

@propertyWrapper
struct ValidatedInt {
    private var value: Int
    private let validator: (Int) -> ValidationResult

    var wrappedValue: Int {
        get { value }
        set {
            let result = validator(newValue)
            if case .valid = result {
                value = newValue
            } else {
                print("Validation error: \(result.reason ?? "Unknown")")
            }
        }
    }

    init(wrappedValue: Int, validator: @escaping (Int) -> ValidationResult) {
        self.value = wrappedValue
        self.validator = validator
    }
}

// 7. User Model with Validation
struct ValidatedUser {
    @ValidatedString(validator: { value in
        value.trimmingCharacters(in: .whitespacesAndNewlines).count >= 3
            ? .valid
            : .invalid(reason: "Username must be at least 3 characters")
    })
    var username: String = ""

    @ValidatedString(validator: GenericValidator<String>.email().validate)
    var email: String = ""

    @ValidatedInt(validator: GenericValidator<Int>.range(min: 18, max: 120).validate)
    var age: Int = 18
}

// 8. Async Validation
class AsyncValidator {

    func validateUsernameAvailable(_ username: String) async throws -> Bool {
        // Simulate API call
        try await Task.sleep(nanoseconds: 500_000_000) // 0.5 seconds

        let takenUsernames = ["admin", "root", "system", "user"]
        return !takenUsernames.contains(username.lowercased())
    }

    func validateEmailExists(_ email: String) async throws -> Bool {
        // Simulate API call
        try await Task.sleep(nanoseconds: 500_000_000)

        return email.contains("@example.com")
    }

    func validateUserAsync(username: String, email: String) async -> [String] {
        var errors: [String] = []

        // Sync validations first
        switch GenericValidator.notEmpty().minLength(3).validate(username) {
        case .invalid(let reason): errors.append(reason)
        default: break
        }

        switch GenericValidator.email().validate(email) {
        case .invalid(let reason): errors.append(reason)
        default: break
        }

        if !errors.isEmpty { return errors }

        // Async validations
        async let usernameAvailable = validateUsernameAvailable(username)
        async let emailExists = validateEmailExists(email)

        do {
            let available = try await usernameAvailable
            if !available {
                errors.append("Username is already taken")
            }
        } catch {
            errors.append("Failed to check username availability")
        }

        do {
            let exists = try await emailExists
            if !exists {
                errors.append("Email not found in system")
            }
        } catch {
            errors.append("Failed to verify email")
        }

        return errors
    }
}

// 9. Validation with Context
struct ValidationErrorWithContext {
    let field: String
    let message: String
    let value: Any

    var description: String {
        return "\(field): \(message) (value: \(value))"
    }
}

class ContextValidator {

    func validateRegistration(data: [String: Any]) -> [ValidationErrorWithContext] {
        var errors: [ValidationErrorWithContext] = []

        if let username = data["username"] as? String {
            if username.isEmpty {
                errors.append(ValidationErrorWithContext(field: "username", message: "cannot be empty", value: username))
            } else if username.count < 3 {
                errors.append(ValidationErrorWithContext(field: "username", message: "must be at least 3 characters", value: username))
            }
        } else {
            errors.append(ValidationErrorWithContext(field: "username", message: "is required", value: "nil"))
        }

        if let email = data["email"] as? String {
            let result = GenericValidator.email().validate(email)
            if case .invalid(let reason) = result {
                errors.append(ValidationErrorWithContext(field: "email", message: reason, value: email))
            }
        }

        if let age = data["age"] as? Int {
            let result = GenericValidator.range(min: 18, max: 120, fieldName: "age").validate(age)
            if case .invalid(let reason) = result {
                errors.append(ValidationErrorWithContext(field: "age", message: reason, value: age))
            }
        }

        return errors
    }
}

// 10. Predefined Validation Rules
struct ValidationRule {
    let name: String
    let validate: (Any) -> ValidationResult

    static let notEmpty = ValidationRule(name: "notEmpty") { value in
        guard let str = value as? String else {
            return .invalid(reason: "Value must be a string")
        }
        return str.isEmpty ? .invalid(reason: "cannot be empty") : .valid
    }

    static let positiveNumber = ValidationRule(name: "positiveNumber") { value in
        guard let num = value as? Int else {
            return .invalid(reason: "Value must be a number")
        }
        return num > 0 ? .valid : .invalid(reason: "must be positive")
    }

    static let emailFormat = ValidationRule(name: "emailFormat") { value in
        guard let email = value as? String else {
            return .invalid(reason: "Value must be a string")
        }
        return GenericValidator<String>.email().validate(email)
    }
}

class RuleBasedValidator {
    func validate(value: Any, against rules: [ValidationRule]) -> [ValidationResult] {
        return rules.map { $0.validate(value) }.filter { !$0.isValid }
    }
}

// Main demonstration
func demonstrateParameterValidation() {
    print("=== macOS Swift Parameter Validation Examples ===")

    // 1. Basic validators
    print("\n--- Basic Validators ---")
    do {
        try Validator.validateNotEmpty("test")
        print("Not empty: valid")
    } catch {
        print("Error: \(error)")
    }

    do {
        try Validator.validateEmail("[email protected]")
        print("Email: valid")
    } catch {
        print("Error: \(error)")
    }

    do {
        try Validator.validateRange(15, min: 10, max: 20)
        print("Range: valid")
    } catch {
        print("Error: \(error)")
    }

    // 2. Generic validators
    print("\n--- Generic Validators ---")
    let usernameValidator = GenericValidator.notEmpty().minLength(3).maxLength(20)
    print("Username 'ab': \(usernameValidator.validate("ab"))")
    print("Username 'john': \(usernameValidator.validate("john"))")

    let ageValidator = GenericValidator.range(min: 18, max: 120)
    print("Age 15: \(ageValidator.validate(15))")
    print("Age 25: \(ageValidator.validate(25))")

    // 3. Combined validation
    print("\n--- Combined Validator ---")
    let combined = CombinedValidator()

    let userErrors = combined.validateUser(name: "jo", email: "invalid-email", age: 15)
    print("User validation errors:")
    userErrors.forEach { print("  - \($0)") }

    // 4. Context validation
    print("\n--- Context Validation ---")
    let contextValidator = ContextValidator()

    let registrationData = [
        "username": "ab",
        "email": "not-an-email",
        "age": 15
    ] as [String: Any]

    let contextErrors = contextValidator.validateRegistration(data: registrationData)
    print("Registration errors:")
    contextErrors.forEach { print("  - \($0.description)") }

    // 5. Password validation
    print("\n--- Password Validation ---")
    let combinedValidator = CombinedValidator()

    print("Password 'abc': \(combinedValidator.validatePassword("abc"))")
    print("Password 'abc123': \(combinedValidator.validatePassword("abc123"))")
    print("Password 'Abc123!@': \(combinedValidator.validatePassword("Abc123!@"))")

    // 6. Rule-based validation
    print("\n--- Rule-Based Validation ---")
    let ruleValidator = RuleBasedValidator()
    let results = ruleValidator.validate(value: -5, against: [.positiveNumber, .notEmpty])
    print("Validation results for -5:")
    results.forEach { print("  - \($0)") }

    // 7. Property wrappers
    print("\n--- Property Wrapper Validation ---")
    var user = ValidatedUser(username: "john_doe", email: "[email protected]", age: 25)
    print("Initial user: \(user.username), \(user.email), \(user.age)")

    user.username = "ja"  // Will print validation error
    user.email = "invalid"  // Will print validation error

    print("\n=== All Parameter Validation Examples Completed ===")
}

// Run demonstration
demonstrateParameterValidation()