3

Cocoa アプリケーションで WiFi ネットワークの変更をサブスクライブしたいのですが、サブスクライブする適切なイベントが見つかりません。

WiFi ネットワークの変更に関する NSNotificationCenter 通知はありますか?

4

3 に答える 3

6

私の知る限りではありません。CoreWLANを使用してシステム上のすべての WiFi インターフェイスのリストを取得し、SystemConfigurationフレームワークを使用してそれらのステータスを監視します。

コマンド ラインの例を次に示します (エラー チェックの細かな点が省略され、ARC が必要です)。

#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];
}
于 2013-02-27T01:17:51.670 に答える
3

CWInterface を開いたままにしている限り、CWLinkDidChangeNotification などの通知を使用できます。次のコードでは、i_interfaces は CWInterface の配列を格納する ivar であり、monitorWifi は最初に呼び出す必要があり、listInterfaces はインターフェイスの値を一覧表示し、何かが変更されるたびに handleInterfaceNotification が呼び出されます。

インターフェイスが接続されていない場合、iface.ssid / iface.bssid は nil になることに注意してください。

また、さまざまな通知により、接続/切断ごとに handleInterfaceNotification が複数回呼び出されることに注意してください。

このコードは主にNSNotification の問題から来ています

-(void) listInterfaces;
{
    NSLog(@"listInterfaces");
    [i_interfaces enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
     {
         CWInterface *iface = obj;
         NSLog( @"iface %@, SSID %@, BSSID %@", iface, iface.ssid, iface.bssid );
     }];
}


-(void) handleInterfaceNotification:(NSNotification*) notification;
{
    NSLog(@"Notification Received");
    [self listInterfaces];
}

- (void) monitorWifi;
{
    NSLog(@"monitorWifi");

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterfaceNotification:) name:CWModeDidChangeNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterfaceNotification:) name:CWSSIDDidChangeNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterfaceNotification:) name:CWBSSIDDidChangeNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterfaceNotification:) name:CWCountryCodeDidChangeNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterfaceNotification:) name:CWLinkDidChangeNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterfaceNotification:) name:CWPowerDidChangeNotification object:nil];

    NSMutableArray* ifaces = [NSMutableArray new];
    NSSet *wifiInterfaces = [CWInterface interfaceNames];
    [wifiInterfaces enumerateObjectsUsingBlock:^(NSString *ifName, BOOL *stop)
     {
         CWInterface *iface = [CWInterface interfaceWithName:ifName];
         if ( iface ) {
             [ifaces addObject:iface];
         }
     }];
    i_interfaces = ifaces;

    [self listInterfaces];
}
于 2013-03-15T09:25:15.927 に答える