Swift 检测以太网/wifi网络更改
我想检测网络何时从以太网变为wifi(或wifi变为以太网)。我想让一个观察员通知我这个变化 可达性还不够好——在这两种情况下,总是通过WiFi返回可达性 附注-Swift 检测以太网/wifi网络更改,swift,macos,Swift,Macos,我想检测网络何时从以太网变为wifi(或wifi变为以太网)。我想让一个观察员通知我这个变化 可达性还不够好——在这两种情况下,总是通过WiFi返回可达性 附注- 以前有一些关于这个话题的问题,但是没有一个有好的答案,因为这些问题已经有一年多的历史了,也许有人已经知道了怎么做你可以在launchd下运行一点bash脚本,监视你感兴趣的界面,并在它们改变时启动一些东西 假设您的有线连接是en0,您可以运行: ./netmon en0 将此脚本另存为netmon,并使用chmod+x netmon
以前有一些关于这个话题的问题,但是没有一个有好的答案,因为这些问题已经有一年多的历史了,也许有人已经知道了怎么做你可以在
launchd
下运行一点bash
脚本,监视你感兴趣的界面,并在它们改变时启动一些东西
假设您的有线连接是en0
,您可以运行:
./netmon en0
将此脚本另存为netmon
,并使用chmod+x netmon使其可执行
#!/bin/bash
interface=$1
# Get current status of interface whose name is passed, e.g. en0
status(){
ifconfig $1 | awk '/status:/{print $2}'
}
# Monitor interface until killed, echoing changes in status
previous=$(status $interface)
while :; do
current=$(status $interface)
if [ $current != $previous ]; then
echo $interface now $current
previous=$current
fi
sleep 5
done
您可以通过SystemConfiguration
模块访问系统网络首选项,该模块可帮助您访问当前位于默认位置的系统首选项存储/Library/preferences/SystemConfiguration/preferences.plist
从那时起,您可以通过SCDynamicStoreNotifyValue(::)
从SCDynamicStore
接收通知,或者通过SCDynamicStoreCopyValue(::)
检索值
直接查找当前主网络服务的示例:
var store = SCDynamicStoreCreate(nil, "Example" as CFString, nil, nil)
var global = SCDynamicStoreCopyValue(store, "State:/Network/Global/IPv4" as CFString)!
var pref = SCPreferencesCreate(nil, "Example" as CFString, nil)
var service = SCNetworkServiceCopy(pref!, global["PrimaryService"] as! CFString)
var interface = SCNetworkServiceGetInterface(service!)
SCNetworkInterfaceGetInterfaceType(interface!) /// Optional("IEEE80211") -> Wi-Fi
或者使用回调创建动态存储,并设置通知键,以便在每次主网络服务更改时接收通知,通知将触发:
var callback: SCDynamicStoreCallBack = { (store, _, _) in
/* Do anything you want */
}
var store = SCDynamicStoreCreate(nil, "Example" as CFString, callback, nil)
SCDynamicStoreSetNotificationKeys(store!, ["State:/Network/Global/IPv4"] as CFArray, nil)
请注意,Mac可以同时具有多个活动接口,其中一些可能是以太网接口,一些可能是WiFi接口。即使您只是监视主接口,也要注意,Mac可以有多个主接口,每个协议一个(例如,IPv4的主接口可能不是IPv6的主接口)
出于演示目的,我假设您希望监视主IPv4接口。下面是您可以复制并粘贴到swift文件并直接从命令行运行的代码(例如,swift someFile.swift
):
当它运行时,尝试切换您的主要IPv4接口,拔出网络电缆,关闭WiFi等,然后观看输出。你可以通过点击键盘上的CTRL+C来停止它。如果你连接到两者,你会怎么办?如果你在Mac SoMy上编程,你可以考虑CordeWLAN框架,但是我想在我的应用程序中包括WiFi/Ethernet检测,所以当用户运行这个应用程序时,应用程序将收到有关界面更改的通知并执行一些操作。@Roee84我已更新了答案以包含通知示例:)谢谢,但我想在我的应用程序中包含wifi/以太网检测,因此当用户运行应用程序时,应用程序将收到有关界面更改的通知并执行一些操作。因此,启动一个运行我的脚本的新线程,读取其输出并相应地执行操作。
import Foundation
import SystemConfiguration
let DynamicStore = SCDynamicStoreCreate(
nil, "Name of your App" as CFString,
{ ( _, _, _ ) in PrimaryIPv4InterfaceChanged() }, nil)!
func PrimaryIPv4InterfaceChanged ( ) {
guard let ipv4State = SCDynamicStoreCopyValue(DynamicStore,
"State:/Network/Global/IPv4" as CFString) as? [CFString: Any]
else {
print("No primary IPv4 interface available")
return
}
guard let primaryServiceID =
ipv4State[kSCDynamicStorePropNetPrimaryService]
else { return }
let interfaceStateName =
"Setup:/Network/Service/\(primaryServiceID)/Interface"
as CFString
guard let primaryServiceState = SCDynamicStoreCopyValue(
DynamicStore, interfaceStateName) as? [CFString: Any]
else { return }
guard let hardwareType =
primaryServiceState[kSCPropNetInterfaceHardware]
else { return }
switch hardwareType as! CFString {
case kSCEntNetAirPort:
print("Primary IPv4 interface is now WiFi")
case kSCEntNetEthernet:
print("Primary IPv4 interface is now Ethernet")
default:
print("Primary IPv4 interface is something else")
}
}
SCDynamicStoreSetNotificationKeys(
DynamicStore, [ "State:/Network/Global/IPv4" ] as CFArray, nil)
SCDynamicStoreSetDispatchQueue(DynamicStore, DispatchQueue.main)
dispatchMain()