WiFi网络更改是不是有NSNotificationCenter通知?

Posted

技术标签:

【中文标题】WiFi网络更改是不是有NSNotificationCenter通知?【英文标题】:Is there a NSNotificationCenter Notification for WiFi network changes?WiFi网络更改是否有NSNotificationCenter通知? 【发布时间】:2013-02-24 00:26:11 【问题描述】:

我想在我的 Cocoa 应用程序中订阅 WiFi 网络更改,但我找不到合适的事件来订阅。

是否有 NSNotificationCenter 通知 WiFi 网络变化?

【问题讨论】:

【参考方案1】:

据我所知。我会使用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];

【讨论】:

这很好,只需要确保在 XCode 中添加了适当的框架。 此处描述了带有键/属性的列表:developer.apple.com/library/content/documentation/Networking/…“系统配置编程指南”“系统配置架构”【参考方案2】:

只要您保持打开 CWInterface,您就可以使用 CWLinkDidChangeNotification 等通知。在下面的代码中,i_interfaces 是一个 ivar,它存储了一个 CWInterface 数组,monitorWifi 应该在开始时被调用,listInterfaces 列出接口值,handleInterfaceNotification 在任何变化时都会被调用。

注意iface.ssid / iface.bssid在接口未连接时为nil。

另请注意,由于各种通知,每次连接/断开连接都会多次调用handleInterfaceNotification。

这段代码主要来自NSNotification troubles

-(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];

【讨论】:

【参考方案3】:

高度赞赏。我需要从 Swift 中执行此操作,所以这里有一些 Swift 代码可以帮助您入门:

func callback(store: SCDynamicStore, changedKeys: CFArray, 
              context: UnsafeMutableRawPointer?) -> Void 
    // Do the magic


// Connect to the store
guard let store = SCDynamicStoreCreate(nil, "myapp" as CFString, callback, nil) else 
    print("Could not connect to store")
    abort()


// Setup the notification mechanism for any IPv4 event
var keys = [CFString]()
keys.append("State:/Network/Global/IPv4" as CFString)
SCDynamicStoreSetNotificationKeys(store, keys as CFArray, nil)

// Go into the loop
let runloop = SCDynamicStoreCreateRunLoopSource(nil, store, 0)
let currentLoop = RunLoop.current.getCFRunLoop()
let modes = CFRunLoopMode.commonModes
CFRunLoopAddSource(currentLoop, runloop, modes)
RunLoop.current.run()

【讨论】:

以上是关于WiFi网络更改是不是有NSNotificationCenter通知?的主要内容,如果未能解决你的问题,请参考以下文章

ios 怎么判断wifi是不是接入了互联网

如何查看当前WIFI网络环境是不是安全

在 Linux 上从 Python 连接到受保护的 WiFi

Android 判断网络是不是可用以及网络类型(WIFI,2G,3G,4G)

笔记本电脑连不上wifi怎么办

iOS 开发,判断手机WiFi是不是打开及获取WiFi名称