我想在我的Cocoa應用程序中訂閱WiFi網絡更改,但我一直無法找到適合的訂閱事件。是否有針對WiFi網絡更改的NSNotificationCenter通知?
是否有針對WiFi網絡更改的NSNotificationCenter通知?
我想在我的Cocoa應用程序中訂閱WiFi網絡更改,但我一直無法找到適合的訂閱事件。是否有針對WiFi網絡更改的NSNotificationCenter通知?
是否有針對WiFi網絡更改的NSNotificationCenter通知?
不是我所知。我將使用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];
}
只要拿着打開一個CWInterface,可以使用CWLinkDidChangeNotification等通知。在以下代碼中,i_interfaces是存儲CWInterface數組的ivar,應在開始時調用monitorWifi,listInterfaces列出接口值,並且每當有任何更改時調用handleInterfaceNotification。
請注意,當接口未連接時,iface.ssid/iface.bssid將爲零。
另請注意,由於各種通知,每次連接/斷開連接都會多次調用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];
}
高度讚賞。我需要從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()
這很好,只需要確保適當的框架被添加到XCode中。 – johndbritton 2013-02-28 07:07:02
具有鍵/屬性的列表在此處描述:https://developer.apple.com/library/content/documentation/Networking/Conceptual/SystemConfigFrameworks/SC_UnderstandSchema/SC_UnderstandSchema.html「系統配置編程指南」「系統配置架構」 – 2017-11-21 14:58:05