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()