Fonctions Mobiles macOS Objective-C - Exemples

Exemples fonctions mobiles macOS Objective-C incluant informations appareil, état réseau feedback système

💻 Informations Appareil objectivec

🟢 simple ⭐⭐⭐

Obtenir modèle appareil, version système informations matérielles via NSProcessInfo NSHost

⏱️ 25 min 🏷️ objectivec, macos, device info
Prerequisites: Objective-C basics, Foundation framework
// macOS Objective-C Device Information Examples
// Using Foundation framework

#import <Foundation/Foundation.h>
#import <sys/sysctl.h>
#import <mach/mach.h>
#import <mach/mach_host.h>

// MARK: - 1. System Information

@interface SystemInfo : NSObject

+ (NSString *)getSystemVersion;
+ (NSString *)getSystemBuildVersion;
+ (NSString *)getHostName;
+ (NSString *)getUserName;
+ (NSString *)getDeviceModel;
+ (NSString *)getCPUModel;
+ (NSInteger)getCPUCount;
+ (unsigned long long)getTotalMemory;
+ (unsigned long long)getTotalDiskSpace;

@end

@implementation SystemInfo

+ (NSString *)getSystemVersion {
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
    NSOperatingSystemVersion version = processInfo.operatingSystemVersion;

    NSString *versionString = [NSString stringWithFormat:@"%ld.%ld.%ld",
                              (long)version.majorVersion,
                              (long)version.minorVersion,
                              (long)version.patchVersion];

    NSLog(@"macOS Version: %@", versionString);
    return versionString;
}

+ (NSString *)getSystemBuildVersion {
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
    NSString *buildVersion = processInfo.operatingSystemVersionString;

    NSLog(@"Build Version: %@", buildVersion);
    return buildVersion;
}

+ (NSString *)getHostName {
    NSString *hostName = [[NSHost currentHost] name];
    NSLog(@"Host Name: %@", hostName);
    return hostName;
}

+ (NSString *)getUserName {
    NSString *userName = NSUserName();
    NSLog(@"User Name: %@", userName);
    return userName;
}

+ (NSString *)getDeviceModel {
    size_t len;
    char *model;

    sysctlbyname("hw.model", NULL, &len, NULL, 0);
    model = malloc(len * sizeof(char));
    sysctlbyname("hw.model", model, &len, NULL, 0);

    NSString *deviceModel = [NSString stringWithUTF8String:model];
    free(model);

    NSLog(@"Device Model: %@", deviceModel);
    return deviceModel;
}

+ (NSString *)getCPUModel {
    size_t len;
    char *cpu;

    sysctlbyname("machdep.cpu.brand_string", NULL, &len, NULL, 0);
    cpu = malloc(len * sizeof(char));
    sysctlbyname("machdep.cpu.brand_string", cpu, &len, NULL, 0);

    NSString *cpuModel = [NSString stringWithUTF8String:cpu];
    free(cpu);

    NSLog(@"CPU Model: %@", cpuModel);
    return cpuModel;
}

+ (NSInteger)getCPUCount {
    NSInteger cpuCount = [[NSProcessInfo processInfo] processorCount];
    NSLog(@"CPU Count: %ld", (long)cpuCount);
    return cpuCount;
}

+ (unsigned long long)getTotalMemory {
    unsigned long long totalMemory = [[NSProcessInfo processInfo] physicalMemory];

    NSLog(@"Total Memory: %llu MB (%.2f GB)",
          totalMemory / 1024 / 1024,
          (double)totalMemory / 1024 / 1024 / 1024);

    return totalMemory;
}

+ (unsigned long long)getTotalDiskSpace {
    NSError *error = nil;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    if (paths.count > 0) {
        NSString *documentsPath = paths.firstObject;
        NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:documentsPath
                                                                                          error:&error];

        if (!error) {
            unsigned long long totalSpace = [attributes[NSFileSystemSize] unsignedLongLongValue];
            unsigned long long freeSpace = [attributes[NSFileSystemFreeSize] unsignedLongLongValue];

            NSLog(@"Total Disk Space: %.2f GB", (double)totalSpace / 1024 / 1024 / 1024);
            NSLog(@"Free Disk Space: %.2f GB", (double)freeSpace / 1024 / 1024 / 1024);

            return totalSpace;
        }
    }

    return 0;
}

@end

// MARK: - 2. Hardware Information

@interface HardwareInfo : NSObject

+ (NSDictionary *)getDetailedSystemInfo;
+ (NSInteger)getActiveCPUCores;
+ (NSInteger)getTotalCPUCores;
+ (NSUInteger)getL1CacheSize;
+ (NSUInteger)getL2CacheSize;
+ (NSUInteger)getL3CacheSize;
+ (double)getCPUFrequency;

@end

@implementation HardwareInfo

+ (NSDictionary *)getDetailedSystemInfo {
    NSMutableDictionary *info = [NSMutableDictionary dictionary];

    // System info
    info[@"systemVersion"] = [SystemInfo getSystemVersion];
    info[@"buildVersion"] = [SystemInfo getSystemBuildVersion];
    info[@"deviceModel"] = [SystemInfo getDeviceModel];
    info[@"cpuModel"] = [SystemInfo getCPUModel];
    info[@"cpuCount"] = @([SystemInfo getCPUCount]);
    info[@"totalMemory"] = @([SystemInfo getTotalMemory]);

    // Host info
    info[@"hostName"] = [SystemInfo getHostName];
    info[@"userName"] = [SystemInfo getUserName];

    // Active cores
    info[@"activeCPUCores"] = @([self getActiveCPUCores]);
    info[@"totalCPUCores"] = @([self getTotalCPUCores]);

    NSLog(@"\n=== Detailed System Info ===");
    for (NSString *key in info) {
        NSLog(@"%@: %@", key, info[key]);
    }

    return [info copy];
}

+ (NSInteger)getActiveCPUCores {
    host_basic_info_data_t hostInfo;
    mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;

    host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &count);

    NSInteger activeCores = hostInfo.avail_cpus;
    NSLog(@"Active CPU Cores: %ld", (long)activeCores);

    return activeCores;
}

+ (NSInteger)getTotalCPUCores {
    host_basic_info_data_t hostInfo;
    mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;

    host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &count);

    NSInteger totalCores = hostInfo.max_cpus;
    NSLog(@"Total CPU Cores: %ld", (long)totalCores);

    return totalCores;
}

+ (NSUInteger)getL1CacheSize {
    size_t size;
    sysctlbyname("hw.l1icachesize", NULL, &size, NULL, 0);

    if (size > 0) {
        unsigned long long cacheSize;
        sysctlbyname("hw.l1icachesize", &cacheSize, &size, NULL, 0);
        NSLog(@"L1 Cache Size: %llu KB", cacheSize / 1024);
        return (NSUInteger)cacheSize;
    }

    return 0;
}

+ (NSUInteger)getL2CacheSize {
    size_t size;
    sysctlbyname("hw.l2cachesize", NULL, &size, NULL, 0);

    if (size > 0) {
        unsigned long long cacheSize;
        sysctlbyname("hw.l2cachesize", &cacheSize, &size, NULL, 0);
        NSLog(@"L2 Cache Size: %llu KB", cacheSize / 1024);
        return (NSUInteger)cacheSize;
    }

    return 0;
}

+ (NSUInteger)getL3CacheSize {
    size_t size;
    sysctlbyname("hw.l3cachesize", NULL, &size, NULL, 0);

    if (size > 0) {
        unsigned long long cacheSize;
        sysctlbyname("hw.l3cachesize", &cacheSize, &size, NULL, 0);
        NSLog(@"L3 Cache Size: %llu KB", cacheSize / 1024);
        return (NSUInteger)cacheSize;
    }

    return 0;
}

+ (double)getCPUFrequency {
    unsigned long long freq = 0;
    size_t len = sizeof(freq);

    sysctlbyname("hw.cpufrequency", &freq, &len, NULL, 0);

    double frequencyGHz = (double)freq / 1000000000.0;
    NSLog(@"CPU Frequency: %.2f GHz", frequencyGHz);

    return frequencyGHz;
}

@end

// MARK: - 3. Process Information

@interface ProcessInfo : NSObject

+ (NSDictionary *)getCurrentProcessInfo;
+ (NSInteger)getProcessID;
+ (NSString *)getProcessName;
+ (NSString *)getExecutablePath;
+ (NSString *)getBundlePath;
+ (NSTimeInterval)getProcessUptime;
+ (double)getCPUUsage;
+ (unsigned long long)getMemoryUsage;

@end

@implementation ProcessInfo

+ (NSDictionary *)getCurrentProcessInfo {
    NSMutableDictionary *info = [NSMutableDictionary dictionary];

    info[@"processID"] = @([self getProcessID]);
    info[@"processName"] = [self getProcessName];
    info[@"executablePath"] = [self getExecutablePath];
    info[@"bundlePath"] = [self getBundlePath];
    info[@"uptime"] = @([self getProcessUptime]);
    info[@"cpuUsage"] = @([self getCPUUsage]);
    info[@"memoryUsage"] = @([self getMemoryUsage]);

    return [info copy];
}

+ (NSInteger)getProcessID {
    pid_t pid = [[NSProcessInfo processInfo] processIdentifier];
    NSLog(@"Process ID: %d", pid);
    return pid;
}

+ (NSString *)getProcessName {
    NSString *processName = [[NSProcessInfo processInfo] processName];
    NSLog(@"Process Name: %@", processName);
    return processName;
}

+ (NSString *)getExecutablePath {
    NSString *executablePath = [[NSBundle mainBundle] executablePath];
    NSLog(@"Executable Path: %@", executablePath);
    return executablePath;
}

+ (NSString *)getBundlePath {
    NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
    NSLog(@"Bundle Path: %@", bundlePath);
    return bundlePath;
}

+ (NSTimeInterval)getProcessUptime {
    NSTimeInterval uptime = [[NSProcessInfo processInfo] systemUptime];
    NSLog(@"System Uptime: %.0f seconds (%.1f minutes)", uptime, uptime / 60);
    return uptime;
}

+ (double)getCPUUsage {
    kern_return_t kr;
    task_info_data_t info;
    mach_msg_type_number_t count;

    count = TASK_BASIC_INFO_COUNT;
    kr = task_info(mach_task_self(),
                  TASK_BASIC_INFO,
                  (task_info_t)info,
                  &count);

    if (kr != KERN_SUCCESS) {
        return 0.0;
    }

    task_basic_info_t basicInfo = (task_basic_info_t)info;
    double cpuUsage = basicInfo->cpu_usage / (double)TH_USAGE_SCALE * 100.0;

    NSLog(@"CPU Usage: %.1f%%", cpuUsage);
    return cpuUsage;
}

+ (unsigned long long)getMemoryUsage {
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);

    kern_return_t kerr = task_info(mach_task_self(),
                                   TASK_BASIC_INFO,
                                   (task_info_t)&info,
                                   &size);

    if (kerr == KERN_SUCCESS) {
        unsigned long long memoryUsage = info.resident_size;
        NSLog(@"Memory Usage: %.2f MB", (double)memoryUsage / 1024 / 1024);
        return memoryUsage;
    }

    return 0;
}

@end

// MARK: - 4. Environment Information

@interface EnvironmentInfo : NSObject

+ (NSDictionary *)getEnvironmentInfo;
+ (NSString *)getLocalTimeZone;
+ (NSString *)getCalendarIdentifier;
+ (NSLocale *)getCurrentLocale;
+ (NSString *)getPreferredLanguage;
+ (NSArray<NSString *> *)getPreferredLanguages;

@end

@implementation EnvironmentInfo

+ (NSDictionary *)getEnvironmentInfo {
    NSMutableDictionary *info = [NSMutableDictionary dictionary];

    info[@"timeZone"] = [self getLocalTimeZone];
    info[@"calendar"] = [self getCalendarIdentifier];
    info[@"locale"] = [self getCurrentLocale].localeIdentifier;
    info[@"preferredLanguage"] = [self getPreferredLanguage];
    info[@"preferredLanguages"] = [self getPreferredLanguages];

    return [info copy];
}

+ (NSString *)getLocalTimeZone {
    NSTimeZone *localTimeZone = [NSTimeZone localTimeZone];
    NSString *tzName = localTimeZone.name;
    NSLog(@"Time Zone: %@", tzName);
    return tzName;
}

+ (NSString *)getCalendarIdentifier {
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSString *calendarId = calendar.calendarIdentifier;
    NSLog(@"Calendar: %@", calendarId);
    return calendarId;
}

+ (NSLocale *)getCurrentLocale {
    NSLocale *currentLocale = [NSLocale currentLocale];
    NSLog(@"Locale: %@", currentLocale.localeIdentifier);
    return currentLocale;
}

+ (NSString *)getPreferredLanguage {
    NSString *language = [[NSLocale preferredLanguages] firstObject];
    NSLog(@"Preferred Language: %@", language);
    return language;
}

+ (NSArray<NSString *> *)getPreferredLanguages {
    NSArray<NSString *> *languages = [NSLocale preferredLanguages];
    NSLog(@"Preferred Languages: %@", languages);
    return languages;
}

@end

// MARK: - 5. Screen Information

@interface ScreenInfo : NSObject

+ (NSSize)getMainScreenSize;
+ (NSRect)getMainScreenFrame;
+ (CGFloat)getMainScreenScale;
+ (NSArray<NSScreen *> *)getAllScreens;
+ (NSInteger)getScreenCount;

@end

@implementation ScreenInfo

+ (NSSize)getMainScreenSize {
    NSSize screenSize = [NSScreen mainScreen].frame.size;
    NSLog(@"Screen Size: %.0fx%.0f", screenSize.width, screenSize.height);
    return screenSize;
}

+ (NSRect)getMainScreenFrame {
    NSRect frame = [NSScreen mainScreen].frame;
    NSLog(@"Screen Frame: %@", NSStringFromRect(frame));
    return frame;
}

+ (CGFloat)getMainScreenScale {
    CGFloat scale = [NSScreen mainScreen].backingScaleFactor;
    NSLog(@"Screen Scale: %.1f", scale);
    return scale;
}

+ (NSArray<NSScreen *> *)getAllScreens {
    NSArray<NSScreen *> *screens = [NSScreen screens];
    NSLog(@"Number of Screens: %lu", (unsigned long)screens.count);
    return screens;
}

+ (NSInteger)getScreenCount {
    NSInteger count = [NSScreen screens].count;
    NSLog(@"Screen Count: %ld", (long)count);
    return count;
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C Device Information Examples ===\n");

        // 1. Basic system information
        NSLog(@"--- 1. Basic System Information ---");
        [SystemInfo getSystemVersion];
        [SystemInfo getSystemBuildVersion];
        [SystemInfo getHostName];
        [SystemInfo getUserName];
        [SystemInfo getDeviceModel];
        [SystemInfo getCPUModel];
        [SystemInfo getCPUCount];
        [SystemInfo getTotalMemory];
        [SystemInfo getTotalDiskSpace];

        // 2. Detailed hardware information
        NSLog(@"\n--- 2. Hardware Information ---");
        [HardwareInfo getDetailedSystemInfo];
        [HardwareInfo getActiveCPUCores];
        [HardwareInfo getTotalCPUCores];
        [HardwareInfo getCPUFrequency];

        // 3. Process information
        NSLog(@"\n--- 3. Process Information ---");
        [ProcessInfo getProcessID];
        [ProcessInfo getProcessName];
        [ProcessInfo getProcessUptime];
        [ProcessInfo getCPUUsage];
        [ProcessInfo getMemoryUsage];

        // 4. Environment information
        NSLog(@"\n--- 4. Environment Information ---");
        [EnvironmentInfo getEnvironmentInfo];

        // 5. Screen information
        NSLog(@"\n--- 5. Screen Information ---");
        [ScreenInfo getMainScreenSize];
        [ScreenInfo getMainScreenScale];
        [ScreenInfo getScreenCount];

        // Summary
        NSLog(@"\n=== Device Information Summary ===");
        NSLog(@"macOS %@ on %@", [SystemInfo getSystemVersion], [SystemInfo getDeviceModel]);
        NSLog(@"%@ with %ld cores", [SystemInfo getCPUModel], (long)[SystemInfo getCPUCount]);
        NSLog(@"%.2f GB RAM, %.2f GHz",
              (double)[SystemInfo getTotalMemory] / 1024 / 1024 / 1024,
              [HardwareInfo getCPUFrequency]);

        NSLog(@"\n=== Device Information Examples Completed ===");
    }

    return 0;
}

💻 Feedback Système objectivec

🟢 simple ⭐⭐

Fournir feedback audio visuel via NSHapticFeedback NSSound NSUserNotification

⏱️ 20 min 🏷️ objectivec, macos, feedback
Prerequisites: Objective-C basics, AppKit framework
// macOS Objective-C System Feedback Examples
// Using AppKit and Foundation frameworks

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

// MARK: - 1. System Sound Feedback

@interface SoundFeedback : NSObject

+ (void)playBeep;
+ (void)playSystemSound:(NSString *)soundName;
+ (void)playAlertSound;
+ (void)playErrorSound;
+ (void)playSuccessSound;

@end

@implementation SoundFeedback

+ (void)playBeep {
    NSBeep();
    NSLog(@"System beep played");
}

+ (void)playSystemSound:(NSString *)soundName {
    NSSound *sound = [[NSSound alloc] initWithNamed:soundName];

    if (sound) {
        [sound play];
        NSLog(@"Playing system sound: %@", soundName);
    } else {
        NSLog(@"Sound not found: %@", soundName);
    }
}

+ (void)playAlertSound {
    [self playSystemSound:@"Frog"];  // System alert sound
    NSLog(@"Alert sound played");
}

+ (void)playErrorSound {
    [self playSystemSound:@"Basso"];  // Error sound
    NSLog(@"Error sound played");
}

+ (void)playSuccessSound {
    [self playSystemSound:@"Glass"];  // Success sound
    NSLog(@"Success sound played");
}

@end

// MARK: - 2. Haptic Feedback (macOS 10.11+)

@interface HapticFeedbackHelper : NSObject

+ (void)performGenericFeedback;
+ (void)performAlignmentFeedback;
+ (void)performLevelChangeFeedback;

@end

@implementation HapticFeedbackHelper

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100

+ (void)performGenericFeedback {
    if (@available(macOS 10.11, *)) {
        // Create a haptic feedback pattern
        NSHapticFeedbackManager *manager = [NSHapticFeedbackManager defaultPerformer];
        NSHapticFeedbackPattern pattern = NSHapticFeedbackPatternGeneric;

        [manager performFeedbackPattern:pattern
                        performanceTime:NSHapticFeedbackPerformanceTimeDefault
                              error:nil];

        NSLog(@"Generic haptic feedback performed");
    } else {
        NSLog(@"Haptic feedback not available (requires macOS 10.11+)");
    }
}

+ (void)performAlignmentFeedback {
    if (@available(macOS 10.11, *)) {
        NSHapticFeedbackManager *manager = [NSHapticFeedbackManager defaultPerformer];
        NSHapticFeedbackPattern pattern = NSHapticFeedbackPatternAlignment;

        [manager performFeedbackPattern:pattern
                        performanceTime:NSHapticFeedbackPerformanceTimeDefault
                              error:nil];

        NSLog(@"Alignment haptic feedback performed");
    }
}

+ (void)performLevelChangeFeedback {
    if (@available(macOS 10.11, *)) {
        NSHapticFeedbackManager *manager = [NSHapticFeedbackManager defaultPerformer];
        NSHapticFeedbackPattern pattern = NSHapticFeedbackPatternLevelChange;

        [manager performFeedbackPattern:pattern
                        performanceTime:NSHapticFeedbackPerformanceTimeDefault
                              error:nil];

        NSLog(@"Level change haptic feedback performed");
    }
}

#else

+ (void)performGenericFeedback {
    NSLog(@"Haptic feedback not available (requires macOS 10.11+)");
}

+ (void)performAlignmentFeedback {
    NSLog(@"Haptic feedback not available (requires macOS 10.11+)");
}

+ (void)performLevelChangeFeedback {
    NSLog(@"Haptic feedback not available (requires macOS 10.11+)");
}

#endif

@end

// MARK: - 3. Visual Feedback

@interface VisualFeedback : NSObject

+ (void)flashScreen;
+ (void)bounceApplicationIcon;
+ (void)bounceApplicationIconUntilActivated:(BOOL)shouldBounce;

@end

@implementation VisualFeedback

+ (void)flashScreen {
    // Flash the screen briefly
    [NSAnimationContext beginGrouping];
    [NSAnimationContext currentContext].duration = 0.1;

    NSWindow *keyWindow = [NSApp keyWindow];

    if (keyWindow) {
        [NSAnimationContext endGrouping];
        NSLog(@"Screen flash performed");

        // Alternative: Use notification to alert user
        NSUserNotification *notification = [[NSUserNotification alloc] init];
        notification.title = @"Attention";
        notification.informativeText = @"Flash effect triggered";
        notification.soundName = NSUserNotificationDefaultSoundName;

        [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
    } else {
        NSLog(@"No key window to flash");
    }
}

+ (void)bounceApplicationIcon {
    NSApplication *app = [NSApplication sharedApplication];
    [app requestUserAttention:NSInformationalRequest];
    NSLog(@"Application icon bounced once");
}

+ (void)bounceApplicationIconUntilActivated:(BOOL)shouldBounce {
    if (shouldBounce) {
        [[NSApplication sharedApplication] requestUserAttention:NSCriticalRequest];
        NSLog(@"Application icon bouncing until activated");
    } else {
        [self bounceApplicationIcon];
    }
}

@end

// MARK: - 4. Notification Feedback

@interface NotificationFeedback : NSObject

+ (void)showNotification:(NSString *)title
                 message:(NSString *)message;

+ (void)showNotificationWithSound:(NSString *)title
                         message:(NSString *)message;

+ (void)showCriticalAlert:(NSString *)title
                   message:(NSString *)message;

@end

@implementation NotificationFeedback

+ (void)showNotification:(NSString *)title
                 message:(NSString *)message {

    NSUserNotification *notification = [[NSUserNotification alloc] init];
    notification.title = title;
    notification.informativeText = message;
    notification.soundName = nil; // No sound

    [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];

    NSLog(@"Notification shown: %@", title);
}

+ (void)showNotificationWithSound:(NSString *)title
                         message:(NSString *)message {

    NSUserNotification *notification = [[NSUserNotification alloc] init];
    notification.title = title;
    notification.informativeText = message;
    notification.soundName = NSUserNotificationDefaultSoundName;

    [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];

    NSLog(@"Notification with sound shown: %@", title);
}

+ (void)showCriticalAlert:(NSString *)title
                   message:(NSString *)message {

    NSUserNotification *notification = [[NSUserNotification alloc] init];
    notification.title = title;
    notification.informativeText = message;
    notification.soundName = NSUserNotificationDefaultSoundName;

    [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];

    // Also bounce the dock icon
    [VisualFeedback bounceApplicationIcon];

    NSLog(@"Critical alert shown: %@", title);
}

@end

// MARK: - 5. Progress Feedback

@interface ProgressFeedback : NSObject

- (instancetype)initForIndeterminateProgress;
- (void)startProgress;
- (void)stopProgress;
- (void)updateProgress:(double)progress;

@end

@implementation ProgressFeedback

{
    NSProgressIndicator *progressIndicator;
    NSWindow *progressWindow;
}

- (instancetype)initForIndeterminateProgress {
    self = [super init];

    if (self) {
        // Create progress window
        progressWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 400, 100)
                                                       styleMask:NSWindowStyleMaskTitled
                                                         backing:NSBackingStoreBuffered
                                                           defer:NO];

        progressWindow.title = @"Progress";

        // Create progress indicator
        progressIndicator = [[NSProgressIndicator alloc] initWithFrame:NSMakeRect(50, 40, 300, 20)];
        progressIndicator.style = NSProgressIndicatorStyleBar;
        progressIndicator.indeterminate = YES;

        [progressWindow.contentView addSubview:progressIndicator];
    }

    return self;
}

- (void)startProgress {
    [progressWindow center];
    [progressWindow makeKeyAndOrderFront:nil];
    [progressIndicator startAnimation:nil];
    NSLog(@"Progress started");
}

- (void)stopProgress {
    [progressIndicator stopAnimation:nil];
    [progressWindow close];
    NSLog(@"Progress stopped");
}

- (void)updateProgress:(double)progress {
    progressIndicator.indeterminate = NO;
    progressIndicator.doubleValue = progress;
    NSLog(@"Progress updated: %.0f%%", progress * 100);
}

@end

// MARK: - 6. Combined Feedback Helper

@interface FeedbackHelper : NSObject

+ (void)notifySuccess:(NSString *)message;
+ (void)notifyError:(NSString *)message;
+ (void)notifyWarning:(NSString *)message;
+ (void)notifyWithSound:(NSString *)title
                message:(NSString *)message;

@end

@implementation FeedbackHelper

+ (void)notifySuccess:(NSString *)message {
    [SoundFeedback playSuccessSound];
    [NotificationFeedback showNotification:@"Success" message:message];
    NSLog(@"Success feedback: %@", message);
}

+ (void)notifyError:(NSString *)message {
    [SoundFeedback playErrorSound];
    [NotificationFeedback showCriticalAlert:@"Error" message:message];
    [VisualFeedback bounceApplicationIcon];
    NSLog(@"Error feedback: %@", message);
}

+ (void)notifyWarning:(NSString *)message {
    [SoundFeedback playAlertSound];
    [NotificationFeedback showNotification:@"Warning" message:message];
    NSLog(@"Warning feedback: %@", message);
}

+ (void)notifyWithSound:(NSString *)title
                message:(NSString *)message {
    [SoundFeedback playBeep];
    [NotificationFeedback showNotificationWithSound:title message:message];
    NSLog(@"Notification with sound: %@ - %@", title, message);
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C System Feedback Examples ===\n");

        // 1. Sound feedback
        NSLog(@"--- 1. Sound Feedback ---");
        NSLog(@"Playing system sounds...");
        [SoundFeedback playBeep];
        [NSThread sleepForTimeInterval:0.5];

        [SoundFeedback performSelector:@selector(playSuccessSound)
                           withObject:nil
                           afterDelay:0.1];

        NSLog(@"\nSound feedback methods:");
        NSLog(@"  - [SoundFeedback playBeep]");
        NSLog(@"  - [SoundFeedback playAlertSound]");
        NSLog(@"  - [SoundFeedback playErrorSound]");
        NSLog(@"  - [SoundFeedback playSuccessSound]\n");

        // 2. Haptic feedback
        NSLog(@"--- 2. Haptic Feedback ---");
        [HapticFeedbackHelper performGenericFeedback];
        [NSThread sleepForTimeInterval:0.5];
        [HapticFeedbackHelper performAlignmentFeedback];

        NSLog(@"\nHaptic feedback methods:");
        NSLog(@"  - [HapticFeedbackHelper performGenericFeedback]");
        NSLog(@"  - [HapticFeedbackHelper performAlignmentFeedback]");
        NSLog(@"  - [HapticFeedbackHelper performLevelChangeFeedback]\n");

        // 3. Visual feedback
        NSLog(@"--- 3. Visual Feedback ---");
        NSLog(@"Bouncing application icon...");
        [VisualFeedback bounceApplicationIcon];

        NSLog(@"\nVisual feedback methods:");
        NSLog(@"  - [VisualFeedback flashScreen]");
        NSLog(@"  - [VisualFeedback bounceApplicationIcon]");
        NSLog(@"  - [VisualFeedback bounceApplicationIconUntilActivated:YES]\n");

        // 4. Notification feedback
        NSLog(@"--- 4. Notification Feedback ---");
        [NotificationFeedback showNotification:@"Test Notification"
                                       message:@"This is a test notification"];

        NSLog(@"\nNotification feedback methods:");
        NSLog(@"  - [NotificationFeedback showNotification:message:]");
        NSLog(@"  - [NotificationFeedback showNotificationWithSound:message:]");
        NSLog(@"  - [NotificationFeedback showCriticalAlert:message:]\n");

        // 5. Combined feedback
        NSLog(@"--- 5. Combined Feedback Helper ---");
        NSLog(@"[FeedbackHelper notifySuccess:@\"Operation completed\\"]");
        NSLog(@"[FeedbackHelper notifyError:@\"Operation failed\"]");
        NSLog(@"[FeedbackHelper notifyWarning:@\"Low disk space\"]");
        NSLog(@"[FeedbackHelper notifyWithSound:@\"Update\" message:@\"New version available\"]\n");

        NSLog(@"=== System Feedback Examples Completed ===");
        NSLog(@"\nNote: Some feedback types require a GUI application context");
    }

    return 0;
}

💻 État Réseau objectivec

🟡 intermediate ⭐⭐⭐

Vérifier état connexion réseau via SCNetworkReachability NSURLSession

⏱️ 30 min 🏷️ objectivec, macos, network
Prerequisites: Objective-C basics, Foundation framework, SystemConfiguration
// macOS Objective-C Network Status Examples
// Using Foundation and SystemConfiguration frameworks

#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>

// MARK: - 1. Basic Network Reachability

typedef NS_ENUM(NSInteger, NetworkStatus) {
    NetworkStatusNotReachable = 0,
    NetworkStatusReachableViaWiFi = 1,
    NetworkStatusReachableViaWWAN = 2
};

@interface NetworkReachability : NSObject

+ (NetworkStatus)currentNetworkStatus;
+ (BOOL)isNetworkAvailable;
+ (BOOL)isWiFiConnected;
+ (BOOL)isCellularConnected;

@end

@implementation NetworkReachability

+ (NetworkStatus)currentNetworkStatus {
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;

    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)&zeroAddress);

    if (!reachability) {
        return NetworkStatusNotReachable;
    }

    SCNetworkReachabilityFlags flags;
    BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
    CFRelease(reachability);

    if (!success) {
        return NetworkStatusNotReachable;
    }

    BOOL isReachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
    BOOL needsConnection = (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0;
    BOOL isWWAN = (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0;

    NetworkStatus status = NetworkStatusNotReachable;

    if (isReachable && !needsConnection) {
        if (isWWAN) {
            status = NetworkStatusReachableViaWWAN;
        } else {
            status = NetworkStatusReachableViaWiFi;
        }
    }

    NSLog(@"Network Status: %ld", (long)status);
    return status;
}

+ (BOOL)isNetworkAvailable {
    NetworkStatus status = [self currentNetworkStatus];
    BOOL available = (status != NetworkStatusNotReachable);
    NSLog(@"Network Available: %@", available ? @"YES" : @"NO");
    return available;
}

+ (BOOL)isWiFiConnected {
    NetworkStatus status = [self currentNetworkStatus];
    BOOL wifi = (status == NetworkStatusReachableViaWiFi);
    NSLog(@"WiFi Connected: %@", wifi ? @"YES" : @"NO");
    return wifi;
}

+ (BOOL)isCellularConnected {
    NetworkStatus status = [self currentNetworkStatus];
    BOOL cellular = (status == NetworkStatusReachableViaWWAN);
    NSLog(@"Cellular Connected: %@", cellular ? @"YES" : @"NO");
    return cellular;
}

@end

// MARK: - 2. Host Reachability Check

@interface HostReachabilityChecker : NSObject

+ (BOOL)isHostReachable:(NSString *)hostName;
+ (void)checkHostReachability:(NSString *)hostName
                  completion:(void (^)(BOOL reachable))completion;

@end

@implementation HostReachabilityChecker

+ (BOOL)isHostReachable:(NSString *)hostName {
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault,
                                                                              [hostName UTF8String]);

    if (!reachability) {
        return NO;
    }

    SCNetworkReachabilityFlags flags;
    BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
    CFRelease(reachability);

    if (!success) {
        return NO;
    }

    BOOL isReachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
    BOOL needsConnection = (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0;

    BOOL reachable = isReachable && !needsConnection;

    NSLog(@"Host '%@' reachable: %@", hostName, reachable ? @"YES" : @"NO");
    return reachable;
}

+ (void)checkHostReachability:(NSString *)hostName
                  completion:(void (^)(BOOL reachable))completion {

    // Use NSURLSession to actually check connectivity
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@", hostName]];

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    config.timeoutIntervalForRequest = 10.0;

    NSURLSession *session = [NSURLSession sessionWithConfiguration:config];

    NSURLSessionDataTask *task = [session dataTaskWithURL:url
                                      completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        BOOL reachable = (error == nil);
        NSLog(@"Host '%@' connectivity check: %@", hostName, reachable ? @"SUCCESS" : @"FAILED");

        if (completion) {
            completion(reachable);
        }
    }];

    [task resume];
}

@end

// MARK: - 3. Network Connection Type

@interface NetworkConnectionInfo : NSObject

+ (NSString *)getConnectionType;
+ (NSDictionary *)getDetailedNetworkInfo;

@end

@implementation NetworkConnectionInfo

+ (NSString *)getConnectionType {
    NetworkStatus status = [NetworkReachability currentNetworkStatus];

    NSString *connectionType;

    switch (status) {
        case NetworkStatusReachableViaWiFi:
            connectionType = @"WiFi";
            break;
        case NetworkStatusReachableViaWWAN:
            connectionType = @"Cellular";
            break;
        default:
            connectionType = @"None";
            break;
    }

    NSLog(@"Connection Type: %@", connectionType);
    return connectionType;
}

+ (NSDictionary *)getDetailedNetworkInfo {
    NSMutableDictionary *info = [NSMutableDictionary dictionary];

    // Get network status
    NetworkStatus status = [NetworkReachability currentNetworkStatus];
    info[@"status"] = @(status);
    info[@"statusText"] = [self getConnectionType];
    info[@"available"] = @([NetworkReachability isNetworkAvailable]);
    info[@"wifi"] = @([NetworkReachability isWiFiConnected]);
    info[@"cellular"] = @([NetworkReachability isCellularConnected]);

    // Get SSID (WiFi network name) if available
    NSString *ssid = [self getCurrentWiFiSSID];
    if (ssid) {
        info[@"ssid"] = ssid;
    }

    NSLog(@"Network Info: %@", info);
    return [info copy];
}

+ (NSString *)getCurrentWiFiSSID {
    CFArrayRef interfaces = CNCopySupportedInterfaces();

    if (!interfaces) {
        return nil;
    }

    NSString *ssid = nil;
    NSArray *interfaceArray = (__bridge NSArray *)interfaces;

    for (NSString *interface in interfaceArray) {
        CFDictionaryRef networkInfo = CNCopyCurrentNetworkInfo((__bridge CFStringRef)interface);

        if (networkInfo) {
            ssid = CFDictionaryGetValue(networkInfo, kCNNetworkInfoKeySSID);
            if (ssid) {
                ssid = [NSString stringWithString:(__bridge NSString *)ssid];
            }
            CFRelease(networkInfo);
            break;
        }
    }

    CFRelease(interfaces);

    if (ssid) {
        NSLog(@"WiFi SSID: %@", ssid);
    }

    return ssid;
}

@end

// MARK: - 4. Network Change Monitor

@interface NetworkMonitor : NSObject

@property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef;
@property (nonatomic, copy) void (^networkChangeBlock)(NetworkStatus status);

- (instancetype)initWithCallback:(void (^)(NetworkStatus status))callback;
- (void)startMonitoring;
- (void)stopMonitoring;

@end

static void NetworkReachabilityCallback(SCNetworkReachabilityRef target,
                                       SCNetworkReachabilityFlags flags,
                                       void *info) {

    NetworkMonitor *monitor = (__bridge NetworkMonitor *)info;

    BOOL isReachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
    BOOL needsConnection = (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0;
    BOOL isWWAN = (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0;

    NetworkStatus status = NetworkStatusNotReachable;

    if (isReachable && !needsConnection) {
        status = isWWAN ? NetworkStatusReachableViaWWAN : NetworkStatusReachableViaWiFi;
    }

    NSLog(@"Network status changed to: %ld", (long)status);

    if (monitor.networkChangeBlock) {
        monitor.networkChangeBlock(status);
    }
}

@implementation NetworkMonitor

- (instancetype)initWithCallback:(void (^)(NetworkStatus status))callback {
    self = [super init];

    if (self) {
        _networkChangeBlock = callback;
    }

    return self;
}

- (void)startMonitoring {
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;

    self.reachabilityRef = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault,
                                                                 (struct sockaddr *)&zeroAddress);

    if (self.reachabilityRef) {
        SCNetworkReachabilityContext context = {0, (__bridge void *)self, NULL, NULL, NULL};

        if (SCNetworkReachabilitySetCallback(self.reachabilityRef,
                                            NetworkReachabilityCallback,
                                            &context)) {

            if (SCNetworkReachabilityScheduleWithRunLoop(self.reachabilityRef,
                                                        CFRunLoopGetCurrent(),
                                                        kCFRunLoopDefaultMode)) {
                NSLog(@"Network monitoring started");
            }
        }
    }
}

- (void)stopMonitoring {
    if (self.reachabilityRef) {
        SCNetworkReachabilityUnscheduleFromRunLoop(self.reachabilityRef,
                                                  CFRunLoopGetCurrent(),
                                                  kCFRunLoopDefaultMode);
        CFRelease(self.reachabilityRef);
        self.reachabilityRef = NULL;
        NSLog(@"Network monitoring stopped");
    }
}

- (void)dealloc {
    [self stopMonitoring];
}

@end

// MARK: - 5. Network Speed Test

@interface NetworkSpeedTest : NSObject

+ (void)testDownloadSpeedWithCompletion:(void (^)(double speedMBps))completion;
+ (void)pingHost:(NSString *)host
       completion:(void (^)(NSTimeInterval pingTime))completion;

@end

@implementation NetworkSpeedTest

+ (void)testDownloadSpeedWithCompletion:(void (^)(double speedMBps))completion {

    NSString *testURLString = @"https://speed.cloudflare.com/__down?bytes=10000000"; // 10MB
    NSURL *url = [NSURL URLWithString:testURLString];

    NSDate *startTime = [NSDate date];

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config];

    NSURLSessionDataTask *task = [session dataTaskWithURL:url
                                      completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"Speed test failed: %@", error.localizedDescription);
            if (completion) {
                completion(0.0);
            }
            return;
        }

        NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startTime];
        double bytes = data.length;
        double mbps = (bytes / 1024 / 1024) / duration;

        NSLog(@"Download speed: %.2f MB/s", mbps);

        if (completion) {
            completion(mbps);
                }
            }];

    [task resume];
}

+ (void)pingHost:(NSString *)host
       completion:(void (^)(NSTimeInterval pingTime))completion {

    // Use NSURLSession to measure round-trip time
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@", host]];

    NSDate *startTime = [NSDate date];

    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    config.timeoutIntervalForRequest = 5.0;

    NSURLSession *session = [NSURLSession sessionWithConfiguration:config];

    NSURLSessionDataTask *task = [session dataTaskWithURL:url
                                      completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSTimeInterval pingTime = [[NSDate date] timeIntervalSinceDate:startTime] * 1000; // Convert to ms

        if (error) {
            NSLog(@"Ping to %@ failed: %@", host, error.localizedDescription);
            pingTime = -1;
        } else {
            NSLog(@"Ping to %@: %.0f ms", host, pingTime);
        }

        if (completion) {
            completion(pingTime);
        }
            }];

    [task resume];
}

@end

// MARK: - Main Demonstration

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"=== macOS Objective-C Network Status Examples ===\n");

        // 1. Basic network status
        NSLog(@"--- 1. Basic Network Status ---");
        BOOL available = [NetworkReachability isNetworkAvailable];
        BOOL wifi = [NetworkReachability isWiFiConnected];
        BOOL cellular = [NetworkReachability isCellularConnected];

        NSLog(@"Network: %@ | WiFi: %@ | Cellular: %@",
              available ? @"Available" : @"Unavailable",
              wifi ? @"Yes" : @"No",
              cellular ? @"Yes" : @"No");

        // 2. Connection type
        NSLog(@"\n--- 2. Connection Type ---");
        NSString *connectionType = [NetworkConnectionInfo getConnectionType];
        NSLog(@"Current connection: %@", connectionType);

        // 3. Host reachability
        NSLog(@"\n--- 3. Host Reachability ---");
        NSArray *testHosts = @[@"apple.com", @"google.com", @"github.com", @"localhost"];

        for (NSString *host in testHosts) {
            [HostReachabilityChecker isHostReachable:host];
        }

        // 4. Detailed network info
        NSLog(@"\n--- 4. Detailed Network Info ---");
        NSDictionary *networkInfo = [NetworkConnectionInfo getDetailedNetworkInfo];
        NSLog(@"%@", networkInfo);

        // 5. Network monitoring setup (demonstration)
        NSLog(@"\n--- 5. Network Monitoring Setup ---");
        NSLog(@"NetworkMonitor *monitor = [[NetworkMonitor alloc] initWithCallback:^(NetworkStatus status) {");
        NSLog(@"    NSLog(@\\\"Network changed to: %ld\\\", (long)status);");
        NSLog(@"}];");
        NSLog(@"[monitor startMonitoring];");
        NSLog(@"// Monitor will automatically detect network changes\n");

        // 6. Speed test example
        NSLog(@"--- 6. Speed Test ---");
        NSLog(@"[NetworkSpeedTest testDownloadSpeedWithCompletion:^(double speedMBps) {");
        NSLog(@"    NSLog(@\\\"Speed: %.2f MB/s\\\", speedMBps);");
        NSLog(@"}];\n");

        // 7. Ping example
        NSLog(@"--- 7. Ping Test ---");
        NSLog(@"[NetworkSpeedTest pingHost:@\\\"google.com\\\" completion:^(NSTimeInterval pingTime) {");
        NSLog(@"    NSLog(@\\\"Ping: %.0f ms\\\", pingTime);");
        NSLog(@"}];\n");

        NSLog(@"=== Network Status Examples Completed ===");
        NSLog(@"\nNote: Some functions like async tests require a run loop");
    }

    return 0;
}