Search code examples
cocoaeventsnsnotificationcenter

Is there a NSNotificationCenter Notification for WiFi network changes?


I'd like to subscribe to WiFi network changes in my Cocoa application, but I haven't been able to find an appropriate event to subscribe to.

Is there an NSNotificationCenter Notification for WiFi network changes?


Solution

  • Not to my knowledge. I would use CoreWLAN to get a list of all WiFi interfaces on the system, and then monitor their status using the SystemConfiguration framework.

    Here's a command-line example (error checking niceties elided, ARC required):

    #import <Foundation/Foundation.h>
    #import <CoreWLAN/CoreWLAN.h>
    #import <SystemConfiguration/SystemConfiguration.h>
    
    void wifi_network_changed(SCDynamicStoreRef store, CFArrayRef changedKeys, void *ctx)
    {
      [(__bridge NSArray *)changedKeys enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
      {
        /* Extract the interface name from the changed key */
        NSString *ifName = [key componentsSeparatedByString:@"/"][3];
        CWInterface *iface = [CWInterface interfaceWithName:ifName];
    
        NSLog(@"%@ status changed: current ssid is %@, security is %ld",
              ifName, iface.ssid, iface.security);
      }];
    }
    
    int main(int argc, char *argv[])
    {
      /* Get a list of all wifi interfaces, and build an array of SCDynamicStore keys to monitor */
      NSSet *wifiInterfaces = [CWInterface interfaceNames];
      NSMutableArray *scKeys = [[NSMutableArray alloc] init];
      [wifiInterfaces enumerateObjectsUsingBlock:^(NSString *ifName, BOOL *stop)
      {
        [scKeys addObject:
          [NSString stringWithFormat:@"State:/Network/Interface/%@/AirPort", ifName]];
      }];
    
      /* Connect to the dynamic store */
      SCDynamicStoreContext ctx = { 0, NULL, NULL, NULL, NULL };
      SCDynamicStoreRef store = SCDynamicStoreCreate(kCFAllocatorDefault,
                                                     CFSTR("myapp"),
                                                     wifi_network_changed,
                                                     &ctx);
    
      /* Start monitoring */
      SCDynamicStoreSetNotificationKeys(store,
                                        (__bridge CFArrayRef)scKeys,
                                        NULL);
    
      CFRunLoopSourceRef src = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault, store, 0);
      CFRunLoopAddSource([[NSRunLoop currentRunLoop] getCFRunLoop],
                         src,
                         kCFRunLoopCommonModes);
      [[NSRunLoop currentRunLoop] run];
    }