Fonctionnalités Mobiles macOS Swift - Exemples

Exemples de fonctionnalités mobiles macOS Swift incluant informations appareil, état réseau et retour vibration

Key Facts

Category
Swift
Items
3
Format Families
sample

Sample Overview

Exemples de fonctionnalités mobiles macOS Swift incluant informations appareil, état réseau et retour vibration This sample set belongs to Swift and can be used to test related workflows inside Elysia Tools.

💻 Récupération Informations Appareil swift

🟢 simple ⭐⭐⭐

Obtenir informations complètes appareil incluant modèle, version OS, capacités matérielles et spécifications système

⏱️ 25 min 🏷️ swift, macos, ios, mobile, device
Prerequisites: Swift basics, Foundation framework, iOS/macOS APIs
// macOS/iOS Swift Device Information Examples
// Using Foundation, UIKit, and SystemConfiguration frameworks

#if os(iOS)
import UIKit
#endif

#if os(macOS)
import AppKit
import IOKit
import IOKit.ps
#endif

import Foundation
import SystemConfiguration

// 1. Basic Device Information
class DeviceInformation {

    #if os(iOS)
    // iOS Device Information
    static func getIOSDeviceInfo() -> DeviceInfo {
        let device = UIDevice.current
        var info = DeviceInfo()

        info.platform = "iOS"
        info.name = device.name
        info.systemName = device.systemName
        info.systemVersion = device.systemVersion
        info.model = device.model
        info.localizedModel = device.localizedModel
        info.userInterfaceIdiom = device.userInterfaceIdiom == .phone ? "iPhone" : "iPad"

        // Battery state
        info.batteryLevel = device.batteryLevel
        info.batteryState = device.batteryState.rawValue
        device.isBatteryMonitoringEnabled = true

        // Screen info
        let screen = UIScreen.main
        info.screenBounds = screen.bounds
        info.screenScale = screen.scale
        info.brightness = screen.brightness

        return info
    }
    #endif

    #if os(macOS)
    // macOS Device Information
    static func getMacOSDeviceInfo() -> DeviceInfo {
        var info = DeviceInfo()
        info.platform = "macOS"

        // Get system info using ProcessInfo
        let processInfo = ProcessInfo.processInfo
        info.systemName = "macOS"
        info.systemVersion = processInfo.operatingSystemVersionString
        info.hostName = processInfo.hostName
        info.physicalMemory = getPhysicalMemory()
        info.processorCount = processInfo.processorCount
        info.activeProcessorCount = processInfo.activeProcessorCount

        // Get hardware info
        let hardwareInfo = getHardwareInfo()
        info.model = hardwareInfo.model
        info.cpuType = hardwareInfo.cpuType
        info.cpuFrequency = hardwareInfo.cpuFrequency

        // Get serial number
        info.serialNumber = getSerialNumber()

        return info
    }

    // Get physical memory
    static func getPhysicalMemory() -> UInt64 {
        var size: UInt64 = 0
        var mib: [Int32] = [CTL_HW, HW_MEMSIZE]
        var len = MemoryLayout<UInt64>.size

        sysctl(&mib, u_int(mib.count), &size, &len, nil, 0)

        return size
    }

    // Get hardware information
    static func getHardwareInfo() -> (model: String, cpuType: String, cpuFrequency: String) {
        var size = 0
        sysctlbyname("hw.model", nil, &size, nil, 0)

        var model = [CChar](repeating: 0, count: size)
        sysctlbyname("hw.model", &model, &size, nil, 0)
        let modelString = String(cString: model)

        // Get CPU info
        var cpufamily: UInt32 = 0
        var cpufamily_size = MemoryLayout<UInt32>.size
        sysctlbyname("hw.cpufamily", &cpufamily, &cpufamily_size, nil, 0)

        var cpufrequency: Int64 = 0
        var cpufrequency_size = MemoryLayout<Int64>.size
        sysctlbyname("hw.cpufrequency", &cpufrequency, &cpufrequency_size, nil, 0)

        let cpuFreqGHz = Double(cpufrequency) / 1_000_000_000

        return (modelString, "CPU Family: \(cpufamily)", String(format: "%.2f GHz", cpuFreqGHz))
    }

    // Get serial number
    static func getSerialNumber() -> String {
        let platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,
                                                           IOServiceMatching("IOPlatformExpertDevice"))

        defer { IOObjectRelease(platformExpert) }

        guard platformExpert != 0 else { return "Unknown" }

        let serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert,
                                                                     kIOPlatformSerialNumberKey as CFString,
                                                                     kCFAllocatorDefault,
                                                                     0)

        guard let serialNumber = serialNumberAsCFString?.takeUnretainedValue() as? String else {
            return "Unknown"
        }

        return serialNumber
    }
    #endif

    // Get common system info
    static func getSystemInfo() -> SystemInfo {
        var sysInfo = SystemInfo()

        let processInfo = ProcessInfo.processInfo
        sysInfo.upTime = processInfo.systemUptime
        sysInfo.processorCount = processInfo.processorCount
        sysInfo.activeProcessorCount = processInfo.activeProcessorCount
        sysInfo.arguments = processInfo.arguments
        sysInfo.environment = processInfo.environment
        sysInfo.processName = processInfo.processName
        sysInfo.globalNumberOfRunningTasks = ProcessInfo.processInfo.processorCount

        return sysInfo
    }

    // Get memory usage
    static func getMemoryUsage() -> MemoryUsage {
        var stats = vm_statistics64()
        var count = UInt32(MemoryLayout<vm_statistics64>.size / MemoryLayout<integer_t>.size)

        let result = withUnsafeMutablePointer(to: &stats) {
            $0.withMemoryRebound(to: integer_t.self, capacity: Int(count)) {
                host_statistics64(mach_host_self(), HOST_VM_INFO64, $0, &count)
            }
        }

        guard result == KERN_SUCCESS else {
            return MemoryUsage()
        }

        let pageSize = vm_kernel_page_size
        let totalMemory = getPhysicalMemory()

        let usedMemory = UInt64(stats.active_count + stats.wire_count) * UInt64(pageSize)
        let freeMemory = UInt64(stats.free_count) * UInt64(pageSize)
        let cachedMemory = UInt64(stats.inactive_count + stats.speculative_count) * UInt64(pageSize)

        return MemoryUsage(
            total: totalMemory,
            used: usedMemory,
            free: freeMemory,
            cached: cachedMemory,
            active: UInt64(stats.active_count) * UInt64(pageSize),
            wired: UInt64(stats.wire_count) * UInt64(pageSize)
        )
    }
}

// 2. Network Status Monitoring
class NetworkStatus {

    // Check if network is available
    static func isNetworkAvailable() -> Bool {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)

        guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, $0)
            }
        }) else {
            return false
        }

        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return false
        }

        let isReachable = flags.contains(.reachable)
        let needsConnection = flags.contains(.connectionRequired)

        return isReachable && !needsConnection
    }

    // Get detailed network status
    static func getNetworkStatus() -> NetworkStatusInfo {
        var status = NetworkStatusInfo()

        // Check reachability
        status.isReachable = isNetworkAvailable()

        // Get connection type
        status.connectionType = getConnectionType()

        // Check WiFi status (iOS only)
        #if os(iOS)
        status.isWiFiEnabled = isWiFiEnabled()
        #endif

        return status
    }

    // Get connection type
    static func getConnectionType() -> String {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)

        guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, $0)
            }
        }) else {
            return "Unknown"
        }

        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return "Unknown"
        }

        let isWWAN = flags.contains(.isWWAN)
        let isReachable = flags.contains(.reachable)

        if isReachable && isWWAN {
            return "Cellular"
        } else if isReachable {
            return "WiFi"
        } else {
            return "No Connection"
        }
    }

    #if os(iOS)
    // Check if WiFi is enabled
    static func isWiFiEnabled() -> Bool {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)

        guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, $0)
            }
        }) else {
            return false
        }

        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return false
        }

        return flags.contains(.reachable) && !flags.contains(.isWWAN)
    }
    #endif

    // Monitor network changes
    static func startNetworkMonitoring(callback: @escaping (NetworkStatusInfo) -> Void) {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)

        guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, $0)
            }
        }) else {
            return
        }

        var context = NetworkCallbackContext(callback: callback)

        SCNetworkReachabilitySetCallback(
            defaultRouteReachability,
            { (_, flags, info) in
                guard let info = info else { return }

                let context = info.assumingMemoryBound(to: NetworkCallbackContext.self).pointee
                let status = NetworkStatusInfo(
                    isReachable: flags.contains(.reachable),
                    connectionType: flags.contains(.isWWAN) ? "Cellular" : "WiFi",
                    isWiFiEnabled: !flags.contains(.isWWAN) && flags.contains(.reachable)
                )
                context.callback(status)
            },
            &context
        )

        SCNetworkReachabilityScheduleWithRunLoop(defaultRouteReachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
    }
}

// 3. Vibration and Haptic Feedback
class VibrationController {

    #if os(iOS)
    // Basic vibration
    static func vibrate() {
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
    }

    // Vibrate with pattern
    static func vibrate(pattern: [VibrationPattern]) {
        for item in pattern {
            DispatchQueue.main.asyncAfter(deadline: .now() + item.delay) {
                if item.vibrate {
                    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
                }
            }
        }
    }

    // Haptic feedback (iOS 10+)
    @available(iOS 10.0, *)
    static func haptic(style: UIImpactFeedbackGenerator.FeedbackStyle) {
        let generator = UIImpactFeedbackGenerator(style: style)
        generator.prepare()
        generator.impactOccurred()
    }

    // Notification haptic
    @available(iOS 10.0, *)
    static func notificationHaptic(type: UINotificationFeedbackGenerator.FeedbackType) {
        let generator = UINotificationFeedbackGenerator()
        generator.prepare()
        generator.notificationOccurred(type)
    }

    // Selection haptic
    @available(iOS 10.0, *)
    static func selectionHaptic() {
        let generator = UISelectionFeedbackGenerator()
        generator.prepare()
        generator.selectionChanged()
    }
    #else
    // macOS doesn't support vibration, but we can provide audio feedback
    static func vibrate() {
        print("Vibration not supported on macOS")
        // Play system sound instead
        NSSound.beep()
    }

    static func vibrate(pattern: [VibrationPattern]) {
        print("Vibration pattern not supported on macOS")
        NSSound.beep()
    }
    #endif

    // Predefined vibration patterns
    static func successVibration() {
        #if os(iOS)
        if #available(iOS 10.0, *) {
            notificationHaptic(type: .success)
        } else {
            vibrate()
        }
        #else
        NSSound.beep()
        #endif
    }

    static func errorVibration() {
        #if os(iOS)
        if #available(iOS 10.0, *) {
            notificationHaptic(type: .error)
        } else {
            vibrate(pattern: [
                VibrationPattern(vibrate: true, delay: 0),
                VibrationPattern(vibrate: false, delay: 0.1),
                VibrationPattern(vibrate: true, delay: 0.1)
            ])
        }
        #else
        NSSound.beep()
        NSSound.beep()
        #endif
    }

    static func warningVibration() {
        #if os(iOS)
        if #available(iOS 10.0, *) {
            notificationHaptic(type: .warning)
        } else {
            vibrate()
        }
        #else
        NSSound.beep()
        #endif
    }
}

// Data Structures
struct DeviceInfo {
    var platform: String = ""
    var name: String = ""
    var systemName: String = ""
    var systemVersion: String = ""
    var model: String = ""
    var localizedModel: String = ""
    var userInterfaceIdiom: String = ""
    var batteryLevel: Float = -1
    var batteryState: Int = 0
    var screenBounds: CGRect = .zero
    var screenScale: CGFloat = 1.0
    var brightness: CGFloat = 0.5
    var hostName: String = ""
    var physicalMemory: UInt64 = 0
    var processorCount: Int = 0
    var activeProcessorCount: Int = 0
    var cpuType: String = ""
    var cpuFrequency: String = ""
    var serialNumber: String = ""
}

struct SystemInfo {
    var upTime: TimeInterval = 0
    var processorCount: Int = 0
    var activeProcessorCount: Int = 0
    var arguments: [String] = []
    var environment: [String: String] = [:]
    var processName: String = ""
    var globalNumberOfRunningTasks: Int = 0
}

struct MemoryUsage {
    var total: UInt64 = 0
    var used: UInt64 = 0
    var free: UInt64 = 0
    var cached: UInt64 = 0
    var active: UInt64 = 0
    var wired: UInt64 = 0
}

struct NetworkStatusInfo {
    var isReachable: Bool = false
    var connectionType: String = "Unknown"
    var isWiFiEnabled: Bool = false
}

struct VibrationPattern {
    var vibrate: Bool
    var delay: TimeInterval
}

struct NetworkCallbackContext {
    var callback: (NetworkStatusInfo) -> Void
}

// Constants
let CTL_HW: Int32 = 6
let HW_MEMSIZE: Int32 = 24

// Helper function
func sysctlbyname(_ name: String, _ oldp: UnsafeMutableRawPointer?, _ oldlenp: UnsafeMutablePointer<Int>?, _ newp: UnsafeRawPointer?, _ newlen: Int) -> Int32 {
    return Darwin.sysctlbyname(name, oldp, oldlenp, newp, newlen)
}

func sysctl(_ name: UnsafeMutablePointer<Int32>, _ namelen: UInt, _ oldp: UnsafeMutableRawPointer?, _ oldlenp: UnsafeMutablePointer<Int>, _ newp: UnsafeRawPointer?, _ newlen: Int) -> Int32 {
    return Darwin.sysctl(name, namelen, oldp, oldlenp, newp, newlen)
}

// Main demonstration
func demonstrateDeviceFeatures() {
    print("=== macOS/iOS Swift Device Features ===\n")

    // 1. Device Information
    print("--- 1. Device Information ---")
    #if os(iOS)
    let deviceInfo = DeviceInformation.getIOSDeviceInfo()
    print("Platform: \(deviceInfo.platform)")
    print("Name: \(deviceInfo.name)")
    print("System: \(deviceInfo.systemName) \(deviceInfo.systemVersion)")
    print("Model: \(deviceInfo.model)")
    print("Idiom: \(deviceInfo.userInterfaceIdiom)")
    print("Battery: \(deviceInfo.batteryLevel * 100)%")
    #elseif os(macOS)
    let deviceInfo = DeviceInformation.getMacOSDeviceInfo()
    print("Platform: \(deviceInfo.platform)")
    print("System: \(deviceInfo.systemVersion)")
    print("Host Name: \(deviceInfo.hostName)")
    print("Model: \(deviceInfo.model)")
    print("CPU: \(deviceInfo.cpuType)")
    print("CPU Frequency: \(deviceInfo.cpuFrequency)")
    print("Serial Number: \(deviceInfo.serialNumber)")
    print("Processors: \(deviceInfo.processorCount)")
    print("Physical Memory: \(formatBytes(deviceInfo.physicalMemory))")
    #endif

    // 2. System Info
    print("\n--- 2. System Information ---")
    let sysInfo = DeviceInformation.getSystemInfo()
    print("Uptime: \(formatUptime(sysInfo.upTime))")
    print("Processors: \(sysInfo.processorCount)")
    print("Active Processors: \(sysInfo.activeProcessorCount)")
    print("Process Name: \(sysInfo.processName)")

    // 3. Memory Usage
    print("\n--- 3. Memory Usage ---")
    let memory = DeviceInformation.getMemoryUsage()
    print("Total: \(formatBytes(memory.total))")
    print("Used: \(formatBytes(memory.used))")
    print("Free: \(formatBytes(memory.free))")
    print("Cached: \(formatBytes(memory.cached))")
    print("Active: \(formatBytes(memory.active))")
    print("Wired: \(formatBytes(memory.wired))")

    // 4. Network Status
    print("\n--- 4. Network Status ---")
    let networkStatus = NetworkStatus.getNetworkStatus()
    print("Reachable: \(networkStatus.isReachable)")
    print("Connection Type: \(networkStatus.connectionType)")
    #if os(iOS)
    print("WiFi Enabled: \(networkStatus.isWiFiEnabled)")
    #endif

    // 5. Vibration Test
    print("\n--- 5. Vibration Test ---")
    print("Testing vibration...")
    VibrationController.vibrate()

    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
        print("Testing success vibration...")
        VibrationController.successVibration()

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            print("Testing warning vibration...")
            VibrationController.warningVibration()

            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                print("Testing error vibration...")
                VibrationController.errorVibration()
            }
        }
    }

    print("\n=== Device Features Demo Completed ===")
}

// Helper functions
func formatBytes(_ bytes: UInt64) -> String {
    let kb = Double(bytes) / 1024
    let mb = kb / 1024
    let gb = mb / 1024

    if gb >= 1 {
        return String(format: "%.2f GB", gb)
    } else if mb >= 1 {
        return String(format: "%.2f MB", mb)
    } else if kb >= 1 {
        return String(format: "%.2f KB", kb)
    } else {
        return "\(bytes) bytes"
    }
}

func formatUptime(_ seconds: TimeInterval) -> String {
    let days = Int(seconds) / 86400
    let hours = Int(seconds) % 86400 / 3600
    let minutes = Int(seconds) % 3600 / 60

    if days > 0 {
        return "\(days)d \(hours)h \(minutes)m"
    } else if hours > 0 {
        return "\(hours)h \(minutes)m"
    } else {
        return "\(minutes)m"
    }
}

// Run demonstration
demonstrateDeviceFeatures()

#if os(iOS)
import AVFoundation
#endif

💻 Surveillance État Réseau swift

🟡 intermediate ⭐⭐⭐

Surveiller connectivité réseau, détecter changements type de connexion et implémenter callbacks d'accessibilité

⏱️ 30 min 🏷️ swift, macos, ios, network, monitoring
Prerequisites: Swift basics, SystemConfiguration framework, Async programming
// macOS/iOS Swift Network Status Monitoring Examples
// Using SystemConfiguration and Network frameworks

import Foundation
import SystemConfiguration
#if os(iOS)
import Network
#endif

// 1. Reachability Manager
class ReachabilityManager {

    var reachability: SCNetworkReachability?
    var isMonitoring = false
    var onNetworkChange: ((Bool) -> Void)?

    // Initialize with default route
    init?() {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)

        guard let reachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, $0)
            }
        }) else {
            return nil
        }

        self.reachability = reachability
    }

    // Start monitoring network changes
    func startMonitoring(callback: @escaping (Bool) -> Void) {
        guard let reachability = reachability else { return }

        self.onNetworkChange = callback
        isMonitoring = true

        var context = SCNetworkReachabilityContext(
            version: 0,
            info: UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()),
            retain: nil,
            release: nil,
            copyDescription: nil
        )

        let callbackFunction: SCNetworkReachabilityCallBack = { (_, flags, info) in
            guard let info = info else { return }

            let manager = Unmanaged<ReachabilityManager>.fromOpaque(info).takeUnretainedValue()
            let isReachable = flags.contains(.reachable) && !flags.contains(.connectionRequired)

            DispatchQueue.main.async {
                manager.onNetworkChange?(isReachable)
            }
        }

        if SCNetworkReachabilitySetCallback(reachability, callbackFunction, &context) {
            SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
        }
    }

    // Stop monitoring
    func stopMonitoring() {
        guard let reachability = reachability, isMonitoring else { return }

        SCNetworkReachabilityUnscheduleFromRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
        isMonitoring = false
        onNetworkChange = nil
    }

    // Check current reachability
    var isReachable: Bool {
        guard let reachability = reachability else { return false }

        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(reachability, &flags) {
            return false
        }

        return flags.contains(.reachable) && !flags.contains(.connectionRequired)
    }

    // Get connection type
    var connectionType: ConnectionType {
        guard let reachability = reachability else { return .unknown }

        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(reachability, &flags) {
            return .unknown
        }

        if !flags.contains(.reachable) {
            return .none
        }

        if flags.contains(.isWWAN) {
            return .cellular
        } else {
            return .wifi
        }
    }

    deinit {
        stopMonitoring()
    }
}

// Connection Type Enum
enum ConnectionType {
    case none
    case wifi
    case cellular
    case unknown

    var description: String {
        switch self {
        case .none: return "No Connection"
        case .wifi: return "WiFi"
        case .cellular: return "Cellular"
        case .unknown: return "Unknown"
        }
    }
}

// 2. Network Monitor with Detailed Info
class NetworkMonitor {

    private var reachabilityManager: ReachabilityManager?
    private var networkHistory: [NetworkEvent] = []
    private let maxHistorySize = 100

    // Start monitoring
    func startMonitoring() {
        reachabilityManager = ReachabilityManager()
        reachabilityManager?.startMonitoring { [weak self] isReachable in
            self?.handleNetworkChange(isReachable: isReachable)
        }

        logInitialStatus()
    }

    // Stop monitoring
    func stopMonitoring() {
        reachabilityManager?.stopMonitoring()
        reachabilityManager = nil
    }

    // Handle network change
    private func handleNetworkChange(isReachable: Bool) {
        let event = NetworkEvent(
            timestamp: Date(),
            isReachable: isReachable,
            connectionType: reachabilityManager?.connectionType ?? .unknown
        )

        networkHistory.append(event)

        // Trim history
        if networkHistory.count > maxHistorySize {
            networkHistory.removeFirst()
        }

        let status = isReachable ? "Connected" : "Disconnected"
        let connection = event.connectionType.description
        print("[\(formatTimestamp(event.timestamp))] Network: \(status) (\(connection))")
    }

    // Log initial status
    private func logInitialStatus() {
        let isReachable = reachabilityManager?.isReachable ?? false
        let connectionType = reachabilityManager?.connectionType ?? .unknown

        let event = NetworkEvent(
            timestamp: Date(),
            isReachable: isReachable,
            connectionType: connectionType
        )

        networkHistory.append(event)

        print("=== Network Monitor Started ===")
        print("Current Status: \(isReachable ? "Connected" : "Disconnected")")
        print("Connection Type: \(connectionType.description)")
    }

    // Get current status
    func getCurrentStatus() -> NetworkStatus {
        return NetworkStatus(
            isReachable: reachabilityManager?.isReachable ?? false,
            connectionType: reachabilityManager?.connectionType ?? .unknown,
            lastChange: networkHistory.last?.timestamp ?? Date()
        )
    }

    // Get network history
    func getNetworkHistory() -> [NetworkEvent] {
        return networkHistory
    }

    // Get statistics
    func getStatistics() -> NetworkStatistics {
        var connectedTime: TimeInterval = 0
        var disconnectedTime: TimeInterval = 0
        var connectionCount = 0
        var disconnectionCount = 0

        for i in 1..<networkHistory.count {
            let previous = networkHistory[i - 1]
            let current = networkHistory[i]
            let duration = current.timestamp.timeIntervalSince(previous.timestamp)

            if previous.isReachable {
                connectedTime += duration
                if !current.isReachable {
                    disconnectionCount += 1
                }
            } else {
                disconnectedTime += duration
                if current.isReachable {
                    connectionCount += 1
                }
            }
        }

        // Add time from last event to now
        if let last = networkHistory.last {
            let duration = Date().timeIntervalSince(last.timestamp)
            if last.isReachable {
                connectedTime += duration
            } else {
                disconnectedTime += duration
            }
        }

        let totalConnectedEvents = networkHistory.filter { $0.isReachable }.count
        let totalDisconnectedEvents = networkHistory.filter { !$0.isReachable }.count

        return NetworkStatistics(
            connectedTime: connectedTime,
            disconnectedTime: disconnectedTime,
            connectionCount: connectionCount,
            disconnectionCount: disconnectionCount,
            totalConnectedEvents: totalConnectedEvents,
            totalDisconnectedEvents: totalDisconnectedEvents
        )
    }
}

// Data Structures
struct NetworkEvent {
    let timestamp: Date
    let isReachable: Bool
    let connectionType: ConnectionType
}

struct NetworkStatus {
    let isReachable: Bool
    let connectionType: ConnectionType
    let lastChange: Date
}

struct NetworkStatistics {
    let connectedTime: TimeInterval
    let disconnectedTime: TimeInterval
    let connectionCount: Int
    let disconnectionCount: Int
    let totalConnectedEvents: Int
    let totalDisconnectedEvents: Int

    var uptimePercentage: Double {
        let total = connectedTime + disconnectedTime
        guard total > 0 else { return 0 }
        return (connectedTime / total) * 100
    }
}

// 3. Bandwidth Monitor (Simplified)
class BandwidthMonitor {

    private var startTime: Date?
    private var startBytes: UInt64 = 0
    private var currentBytes: UInt64 = 0

    // Start monitoring bandwidth
    func startMonitoring() {
        startTime = Date()
        startBytes = getCurrentBytesReceived()
        print("Bandwidth monitoring started")
    }

    // Stop monitoring and get results
    func stopMonitoring() -> BandwidthResult {
        guard let start = startTime else {
            return BandwidthResult(duration: 0, bytesReceived: 0, averageSpeed: 0)
        }

        currentBytes = getCurrentBytesReceived()
        let duration = Date().timeIntervalSince(start)
        let bytesReceived = currentBytes - startBytes
        let averageSpeed = bytesReceived / UInt64(duration)

        startTime = nil
        startBytes = 0

        let result = BandwidthResult(
            duration: duration,
            bytesReceived: bytesReceived,
            averageSpeed: averageSpeed
        )

        print("Bandwidth monitoring stopped:")
        print("  Duration: \(String(format: "%.1f", duration))s")
        print("  Bytes Received: \(formatBytes(bytesReceived))")
        print("  Average Speed: \(formatBytes(averageSpeed))/s")

        return result
    }

    // Get current bytes received (simplified)
    private func getCurrentBytesReceived() -> UInt64 {
        // In a real implementation, you'd use network interface statistics
        // This is a placeholder
        return UInt64.random(in: 1000000...10000000)
    }
}

struct BandwidthResult {
    let duration: TimeInterval
    let bytesReceived: UInt64
    let averageSpeed: UInt64
}

// 4. Connectivity Test
class ConnectivityTest {

    // Test connectivity to a host
    static func testConnection(to host: String, timeout: TimeInterval = 5.0) -> Bool {
        guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else {
            return false
        }

        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(reachability, &flags) {
            return false
        }

        let isReachable = flags.contains(.reachable)
        let needsConnection = flags.contains(.connectionRequired)
        let canConnectAutomatically = flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic)

        return isReachable && (!needsConnection || canConnectAutomatically)
    }

    // Test multiple hosts
    static func testMultipleHosts(_ hosts: [String]) -> [String: Bool] {
        var results: [String: Bool] = [:]

        for host in hosts {
            results[host] = testConnection(to: host)
        }

        return results
    }

    // Ping test (simplified)
    static func ping(_ host: String, count: Int = 4) -> PingResult {
        print("Pinging \(host)...")

        var successfulPings = 0
        var totalLatency: TimeInterval = 0

        for _ in 0..<count {
            let start = Date()

            if testConnection(to: host, timeout: 1.0) {
                let latency = Date().timeIntervalSince(start)
                totalLatency += latency
                successfulPings += 1
            }

            Thread.sleep(forTimeInterval: 0.5)
        }

        let averageLatency = successfulPings > 0 ? totalLatency / Double(successfulPings) : 0
        let packetLoss = ((count - successfulPings) / count) * 100

        let result = PingResult(
            host: host,
            packetsSent: count,
            packetsReceived: successfulPings,
            packetLoss: packetLoss,
            averageLatency: averageLatency
        )

        print("Ping statistics for \(host):")
        print("  Packets: Sent = \(count), Received = \(successfulPings), Lost = \(count - successfulPings)")
        print("  Packet Loss: \(packetLoss)%")
        if successfulPings > 0 {
            print("  Average Latency: \(String(format: "%.2f", averageLatency * 1000))ms")
        }

        return result
    }
}

struct PingResult {
    let host: String
    let packetsSent: Int
    let packetsReceived: Int
    let packetLoss: Int
    let averageLatency: TimeInterval
}

// Helper functions
func formatTimestamp(_ date: Date) -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "HH:mm:ss"
    return formatter.string(from: date)
}

func formatBytes(_ bytes: UInt64) -> String {
    let kb = Double(bytes) / 1024
    let mb = kb / 1024
    let gb = mb / 1024

    if gb >= 1 {
        return String(format: "%.2f GB", gb)
    } else if mb >= 1 {
        return String(format: "%.2f MB", mb)
    } else if kb >= 1 {
        return String(format: "%.2f KB", kb)
    } else {
        return "\(bytes) B"
    }
}

// Main demonstration
func demonstrateNetworkMonitoring() {
    print("=== macOS/iOS Swift Network Status Monitoring ===\n")

    // 1. Basic reachability check
    print("--- 1. Basic Reachability Check ---")
    if let manager = ReachabilityManager() {
        print("Is Reachable: \(manager.isReachable)")
        print("Connection Type: \(manager.connectionType.description)")
    }

    // 2. Start monitoring
    print("\n--- 2. Network Monitoring ---")
    let monitor = NetworkMonitor()
    monitor.startMonitoring()

    // Keep monitoring for a few seconds
    print("Monitoring network changes for 10 seconds...")
    Thread.sleep(forTimeInterval: 10)

    // 3. Get current status
    print("\n--- 3. Current Status ---")
    let status = monitor.getCurrentStatus()
    print("Reachable: \(status.isReachable)")
    print("Connection: \(status.connectionType.description)")
    print("Last Change: \(formatTimestamp(status.lastChange))")

    // 4. Get statistics
    print("\n--- 4. Network Statistics ---")
    let stats = monitor.getStatistics()
    print("Connected Time: \(String(format: "%.1f", stats.connectedTime))s")
    print("Disconnected Time: \(String(format: "%.1f", stats.disconnectedTime))s")
    print("Connection Count: \(stats.connectionCount)")
    print("Disconnection Count: \(stats.disconnectionCount)")
    print("Uptime: \(String(format: "%.1f", stats.uptimePercentage))%")

    // 5. Test multiple hosts
    print("\n--- 5. Host Connectivity Tests ---")
    let hosts = ["apple.com", "google.com", "github.com", "localhost"]
    let results = ConnectivityTest.testMultipleHosts(hosts)

    for (host, reachable) in results {
        print("\(host): \(reachable ? "✓ Reachable" : "✗ Unreachable")")
    }

    // 6. Ping test
    print("\n--- 6. Ping Test ---")
    let pingResult = ConnectivityTest.ping("apple.com", count: 4)

    // 7. Bandwidth monitoring
    print("\n--- 7. Bandwidth Monitoring ---")
    let bandwidthMonitor = BandwidthMonitor()
    bandwidthMonitor.startMonitoring()
    print("Monitoring bandwidth for 5 seconds...")
    Thread.sleep(forTimeInterval: 5)
    bandwidthMonitor.stopMonitoring()

    // Stop monitoring
    monitor.stopMonitoring()

    print("\n=== Network Monitoring Demo Completed ===")
}

// Run demonstration
demonstrateNetworkMonitoring()

💻 Vibration et Retour Haptique swift

🔴 complex ⭐⭐⭐⭐

Implémenter patterns vibration appareil et retour haptique pour notifications utilisateur

⏱️ 30 min 🏷️ swift, macos, ios, haptic, vibration
Prerequisites: Swift basics, CoreHaptics framework, iOS 13+ APIs
// macOS/iOS Swift Vibration and Haptic Feedback Examples
// Using CoreHaptics (iOS 13+) and AudioToolbox

#if os(iOS)
import UIKit
import CoreHaptics
import AudioToolbox
#endif

#if os(macOS)
import AppKit
#endif

import Foundation

// 1. Haptic Engine Manager
class HapticEngineManager {

    #if os(iOS)
    @available(iOS 13.0, *)
    private var hapticEngine: CHHapticEngine?

    // Initialize haptic engine
    @available(iOS 13.0, *)
    func initializeHapticEngine() -> Bool {
        guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else {
            print("Haptics not supported on this device")
            return false
        }

        do {
            hapticEngine = try CHHapticEngine()

            // Handle engine stopped
            hapticEngine?.stoppedHandler = { reason in
                print("Haptic engine stopped: \(reason.rawValue)")
            }

            // Handle engine reset
            hapticEngine?.resetHandler = {
                print("Haptic engine reset")
                do {
                    try self.hapticEngine?.start()
                } catch {
                    print("Error starting haptic engine after reset: \(error)")
                }
            }

            try hapticEngine?.start()
            print("Haptic engine initialized successfully")
            return true

        } catch {
            print("Error creating haptic engine: \(error)")
            return false
        }
    }

    // Stop haptic engine
    @available(iOS 13.0, *)
    func stopHapticEngine() {
        hapticEngine?.stop(completionHandler: { error in
            if let error = error {
                print("Error stopping haptic engine: \(error)")
            }
        })
    }
    #else
    func initializeHapticEngine() -> Bool {
        print("Haptics not supported on macOS")
        return false
    }

    func stopHapticEngine() {
        print("Haptics not supported on macOS")
    }
    #endif
}

// 2. Vibration Patterns
class VibrationPatternManager {

    #if os(iOS)
    // Play vibration pattern using AudioToolbox
    static func playVibrationPattern(_ pattern: VibrationPattern) {
        for item in pattern.items {
            DispatchQueue.main.asyncAfter(deadline: .now() + item.delay) {
                if item.intensity > 0 {
                    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
                }
            }
        }
    }

    // Predefined patterns
    static func notificationPattern() -> VibrationPattern {
        VibrationPattern(items: [
            VibrationItem(intensity: 1, delay: 0),
            VibrationItem(intensity: 0, delay: 0.1),
            VibrationItem(intensity: 1, delay: 0.1)
        ])
    }

    static func alertPattern() -> VibrationPattern {
        VibrationPattern(items: [
            VibrationItem(intensity: 1, delay: 0),
            VibrationItem(intensity: 0, delay: 0.15),
            VibrationItem(intensity: 1, delay: 0.15),
            VibrationItem(intensity: 0, delay: 0.15),
            VibrationItem(intensity: 1, delay: 0.15)
        ])
    }

    static func successPattern() -> VibrationPattern {
        VibrationPattern(items: [
            VibrationItem(intensity: 1, delay: 0),
            VibrationItem(intensity: 0, delay: 0.05),
            VibrationItem(intensity: 1, delay: 0.05)
        ])
    }

    static func errorPattern() -> VibrationPattern {
        VibrationPattern(items: [
            VibrationItem(intensity: 1, delay: 0),
            VibrationItem(intensity: 0, delay: 0.1),
            VibrationItem(intensity: 1, delay: 0.1),
            VibrationItem(intensity: 0, delay: 0.1),
            VibrationItem(intensity: 1, delay: 0.1),
            VibrationItem(intensity: 0, delay: 0.1),
            VibrationItem(intensity: 1, delay: 0.1)
        ])
    }

    static func heartbeatPattern() -> VibrationPattern {
        VibrationPattern(items: [
            VibrationItem(intensity: 1, delay: 0),
            VibrationItem(intensity: 0, delay: 0.15),
            VibrationItem(intensity: 1, delay: 0.15),
            VibrationItem(intensity: 0, delay: 0.3),
            VibrationItem(intensity: 1, delay: 0.3),
            VibrationItem(intensity: 0, delay: 0.15),
            VibrationItem(intensity: 1, delay: 0.15)
        ])
    }
    #else
    static func playVibrationPattern(_ pattern: VibrationPattern) {
        print("Vibration not supported on macOS")
        NSSound.beep()
    }

    static func notificationPattern() -> VibrationPattern {
        VibrationPattern(items: [])
    }

    static func alertPattern() -> VibrationPattern {
        VibrationPattern(items: [])
    }

    static func successPattern() -> VibrationPattern {
        VibrationPattern(items: [])
    }

    static func errorPattern() -> VibrationPattern {
        VibrationPattern(items: [])
    }

    static func heartbeatPattern() -> VibrationPattern {
        VibrationPattern(items: [])
    }
    #endif
}

// 3. Haptic Feedback Manager
class HapticFeedbackManager {

    #if os(iOS)
    // Impact feedback
    @available(iOS 10.0, *)
    static func impact(style: UIImpactFeedbackGenerator.FeedbackStyle) {
        let generator = UIImpactFeedbackGenerator(style: style)
        generator.prepare()
        generator.impactOccurred()
    }

    // Light impact
    @available(iOS 10.0, *)
    static func lightImpact() {
        impact(style: .light)
    }

    // Medium impact
    @available(iOS 10.0, *)
    static func mediumImpact() {
        impact(style: .medium)
    }

    // Heavy impact
    @available(iOS 10.0, *)
    static func heavyImpact() {
        impact(style: .heavy)
    }

    // Soft impact (iOS 13+)
    @available(iOS 13.0, *)
    static func softImpact() {
        impact(style: .soft)
    }

    // Rigid impact (iOS 13+)
    @available(iOS 13.0, *)
    static func rigidImpact() {
        impact(style: .rigid)
    }

    // Notification feedback
    @available(iOS 10.0, *)
    static func notification(_ type: UINotificationFeedbackGenerator.FeedbackType) {
        let generator = UINotificationFeedbackGenerator()
        generator.prepare()
        generator.notificationOccurred(type)
    }

    // Success notification
    @available(iOS 10.0, *)
    static func successNotification() {
        notification(.success)
    }

    // Warning notification
    @available(iOS 10.0, *)
    static func warningNotification() {
        notification(.warning)
    }

    // Error notification
    @available(iOS 10.0, *)
    static func errorNotification() {
        notification(.error)
    }

    // Selection feedback
    @available(iOS 10.0, *)
    static func selectionChanged() {
        let generator = UISelectionFeedbackGenerator()
        generator.prepare()
        generator.selectionChanged()
    }
    #else
    static func impact(style: Int) {
        print("Haptic impact not supported on macOS")
        NSSound.beep()
    }

    static func lightImpact() {
        NSSound.beep()
    }

    static func mediumImpact() {
        NSSound.beep()
    }

    static func heavyImpact() {
        NSSound.beep()
    }

    static func notification(_ type: Int) {
        NSSound.beep()
    }

    static func successNotification() {
        NSSound.beep()
    }

    static func warningNotification() {
        NSSound.beep()
        NSSound.beep()
    }

    static func errorNotification() {
        NSSound.beep()
        NSSound.beep()
        NSSound.beep()
    }

    static func selectionChanged() {
        NSSound.beep()
    }
    #endif
}

// 4. Custom Haptic Patterns
class CustomHapticPatterns {

    #if os(iOS)
    @available(iOS 13.0, *)
    static func playCustomHapticPattern(intensity: Float, sharpness: Float, duration: TimeInterval) {
        guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else {
            print("Haptics not supported")
            return
        }

        do {
            let pattern = try CHHapticPattern(
                events: [
                    CHHapticEvent(eventType: .hapticTransient, parameters: [
                        CHHapticEventParameter(parameterID: .hapticIntensity, value: intensity),
                        CHHapticEventParameter(parameterID: .hapticSharpness, value: sharpness)
                    ], relativeTime: 0)
                ],
                parameters: []
            )

            let engine = try CHHapticEngine()
            try engine.start()

            let player = try engine.makePlayer(with: pattern)
            try player.start(atTime: 0)

            print("Playing custom haptic pattern")

        } catch {
            print("Error playing custom pattern: \(error)")
        }
    }

    @available(iOS 13.0, *)
    static func playContinuousHaptic(intensity: Float, sharpness: Float, duration: TimeInterval) {
        guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else {
            print("Haptics not supported")
            return
        }

        do {
            let pattern = try CHHapticPattern(
                events: [
                    CHHapticEvent(eventType: .hapticContinuous, parameters: [
                        CHHapticEventParameter(parameterID: .hapticIntensity, value: intensity),
                        CHHapticEventParameter(parameterID: .hapticSharpness, value: sharpness)
                    ], relativeTime: 0, duration: duration)
                ],
                parameters: []
            )

            let engine = try CHHapticEngine()
            try engine.start()

            let player = try engine.makePlayer(with: pattern)
            try player.start(atTime: 0)

            print("Playing continuous haptic for \(duration)s")

        } catch {
            print("Error playing continuous haptic: \(error)")
        }
    }

    @available(iOS 13.0, *)
    static func playComplexPattern() {
        guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else {
            print("Haptics not supported")
            return
        }

        do {
            // Create a complex pattern with multiple events
            let pattern = try CHHapticPattern(
                events: [
                    // Tap
                    CHHapticEvent(eventType: .hapticTransient, parameters: [
                        CHHapticEventParameter(parameterID: .hapticIntensity, value: 1.0),
                        CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.5)
                    ], relativeTime: 0),

                    // Hold
                    CHHapticEvent(eventType: .hapticContinuous, parameters: [
                        CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.8),
                        CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.3)
                    ], relativeTime: 0.1, duration: 0.2),

                    // Release
                    CHHapticEvent(eventType: .hapticTransient, parameters: [
                        CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.6),
                        CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.8)
                    ], relativeTime: 0.4)
                ],
                parameters: []
            )

            let engine = try CHHapticEngine()
            try engine.start()

            let player = try engine.makePlayer(with: pattern)
            try player.start(atTime: 0)

            print("Playing complex haptic pattern")

        } catch {
            print("Error playing complex pattern: \(error)")
        }
    }
    #else
    @available(iOS 13.0, *)
    static func playCustomHapticPattern(intensity: Float, sharpness: Float, duration: TimeInterval) {
        print("Custom haptics not supported on macOS")
    }

    @available(iOS 13.0, *)
    static func playContinuousHaptic(intensity: Float, sharpness: Float, duration: TimeInterval) {
        print("Continuous haptics not supported on macOS")
    }

    @available(iOS 13.0, *)
    static func playComplexPattern() {
        print("Complex haptics not supported on macOS")
    }
    #endif
}

// 5. Haptic Notification Manager
class HapticNotificationManager {

    // Complete notification with visual, audio, and haptic feedback
    static func showNotification(type: NotificationType) {
        print("\n=== \(type.title) ===")

        switch type {
        case .success:
            #if os(iOS)
            if #available(iOS 10.0, *) {
                HapticFeedbackManager.successNotification()
            } else {
                VibrationPatternManager.playVibrationPattern(VibrationPatternManager.successPattern())
            }
            #else
            NSSound.beep()
            #endif

        case .warning:
            #if os(iOS)
            if #available(iOS 10.0, *) {
                HapticFeedbackManager.warningNotification()
            } else {
                VibrationPatternManager.playVibrationPattern(VibrationPatternManager.alertPattern())
            }
            #else
            NSSound.beep()
            NSSound.beep()
            #endif

        case .error:
            #if os(iOS)
            if #available(iOS 10.0, *) {
                HapticFeedbackManager.errorNotification()
            } else {
                VibrationPatternManager.playVibrationPattern(VibrationPatternManager.errorPattern())
            }
            #else
            NSSound.beep()
            NSSound.beep()
            NSSound.beep()
            #endif

        case .message:
            #if os(iOS)
            VibrationPatternManager.playVibrationPattern(VibrationPatternManager.notificationPattern())
            #else
            NSSound.beep()
            #endif

        case .reminder:
            #if os(iOS)
            if #available(iOS 10.0, *) {
                HapticFeedbackManager.mediumImpact()
            }
            #else
            NSSound.beep()
            #endif
        }
    }

    // Show progress haptic
    static func showProgressHaptic(progress: Float) {
        #if os(iOS)
        if #available(iOS 10.0, *) {
            let intensity = CHHapticEventParameter.ParameterID.hapticIntensity
            // Gradually increase haptic based on progress
            if progress >= 1.0 {
                HapticFeedbackManager.successNotification()
            } else if progress > 0.75 {
                HapticFeedbackManager.lightImpact()
            }
        }
        #endif
    }
}

// Data Structures
struct VibrationPattern {
    let items: [VibrationItem]
}

struct VibrationItem {
    let intensity: Int
    let delay: TimeInterval
}

enum NotificationType {
    case success
    case warning
    case error
    case message
    case reminder

    var title: String {
        switch self {
        case .success: return "Success"
        case .warning: return "Warning"
        case .error: return "Error"
        case .message: return "Message"
        case .reminder: return "Reminder"
        }
    }
}

// Main demonstration
func demonstrateHapticFeedback() {
    print("=== macOS/iOS Swift Vibration & Haptic Feedback ===\n")

    // Initialize haptic engine
    #if os(iOS)
    if #available(iOS 13.0, *) {
        let engineManager = HapticEngineManager()
        _ = engineManager.initializeHapticEngine()
    }
    #endif

    // 1. Basic impact feedback
    print("--- 1. Impact Feedback ---")
    print("Light impact...")
    HapticFeedbackManager.lightImpact()
    Thread.sleep(forTimeInterval: 0.5)

    print("Medium impact...")
    HapticFeedbackManager.mediumImpact()
    Thread.sleep(forTimeInterval: 0.5)

    print("Heavy impact...")
    HapticFeedbackManager.heavyImpact()
    Thread.sleep(forTimeInterval: 0.5)

    // 2. Selection feedback
    print("\n--- 2. Selection Feedback ---")
    print("Selection changed (3 times)...")
    HapticFeedbackManager.selectionChanged()
    Thread.sleep(forTimeInterval: 0.2)
    HapticFeedbackManager.selectionChanged()
    Thread.sleep(forTimeInterval: 0.2)
    HapticFeedbackManager.selectionChanged()

    // 3. Notification feedback
    print("\n--- 3. Notification Feedback ---")
    print("Success notification...")
    HapticNotificationManager.showNotification(type: .success)
    Thread.sleep(forTimeInterval: 1.0)

    print("Warning notification...")
    HapticNotificationManager.showNotification(type: .warning)
    Thread.sleep(forTimeInterval: 1.0)

    print("Error notification...")
    HapticNotificationManager.showNotification(type: .error)
    Thread.sleep(forTimeInterval: 1.0)

    // 4. Vibration patterns
    print("\n--- 4. Vibration Patterns ---")
    print("Notification pattern...")
    VibrationPatternManager.playVibrationPattern(VibrationPatternManager.notificationPattern())
    Thread.sleep(forTimeInterval: 1.0)

    print("Alert pattern...")
    VibrationPatternManager.playVibrationPattern(VibrationPatternManager.alertPattern())
    Thread.sleep(forTimeInterval: 1.0)

    print("Heartbeat pattern...")
    VibrationPatternManager.playVibrationPattern(VibrationPatternManager.heartbeatPattern())

    // 5. Custom haptics (iOS 13+)
    #if os(iOS)
    if #available(iOS 13.0, *) {
        print("\n--- 5. Custom Haptics ---")
        Thread.sleep(forTimeInterval: 1.0)

        print("Custom pattern (intensity: 0.8, sharpness: 0.5)...")
        CustomHapticPatterns.playCustomHapticPattern(intensity: 0.8, sharpness: 0.5, duration: 0.3)
        Thread.sleep(forTimeInterval: 0.5)

        print("Continuous haptic (0.5s)...")
        CustomHapticPatterns.playContinuousHaptic(intensity: 0.7, sharpness: 0.4, duration: 0.5)
        Thread.sleep(forTimeInterval: 0.6)

        print("Complex pattern...")
        CustomHapticPatterns.playComplexPattern()
    }
    #endif

    // 6. Progress haptics
    print("\n--- 6. Progress Haptics ---")
    print("Simulating progress...")
    for i in 1...5 {
        let progress = Float(i) / 5.0
        print("Progress: \(Int(progress * 100))%")
        HapticNotificationManager.showProgressHaptic(progress: progress)
        Thread.sleep(forTimeInterval: 0.3)
    }

    print("\n=== Haptic Feedback Demo Completed ===")
}

// Run demonstration
demonstrateHapticFeedback()