我想检测网络何时从以太网变为wifi(或从wifi变为以太网)。我希望有一位观察员通知我这一变化。
可达性不够好 - 它总是会在两种情况下都返回ReachableViaWiFi。
P.S - 之前有一些关于这个主题的问题,但没有一个有好的答案,而且由于这些问题已经超过一年了,也许有人已经知道如何做到这一点
答案 0 :(得分:9)
您可以通过SystemConfiguration
模块访问系统网络偏好设置,这有助于您触摸当前位于默认位置/Library/Preferences/SystemConfiguration/preferences.plist
的系统偏好设置商店。
从那时起,您可以SCDynamicStore
通过SCDynamicStoreNotifyValue(_:_:)
接收通知,或按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)
答案 1 :(得分:3)
您可以在bash
下运行一个launchd
脚本来监控您感兴趣的界面,并在更改时启动。
假设您的有线连接是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
答案 2 :(得分:1)
请注意,Mac可以同时具有多个活动接口,其中一些可能是以太网,有些可能是WiFi。即使您仅监视主要接口,也请注意,Mac可以具有多个主要接口,每个协议一个(例如,IPv4的主要接口可能不是IPv6的主要接口)。
出于演示目的,我将假定您要监视主IPv4接口。这是您可以复制并粘贴到快捷文件并直接从命令行运行的代码(例如swift someFile.swift
)
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()
当它正在运行时,请尝试切换您的主要IPv4接口,拉网线,关闭WiFi等,然后观察输出。您可以通过按键盘上的CTRL + C来停止它。