ios - iOS Reachability SCNetworkReachabilitySetCallback 在从 wifi 切换到 anthor wifi 时不回调
问题描述
我想在 iPhone 更换网络时接听电话。
我使用 Apple 指南的 Reachability.m,如下所示:
xxx.m
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
Reachability = [self reachabilityWithAddress: (const struct sockaddr *) &zeroAddress]
可达性.m
BOOL returnValue = NO;
SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
{
if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetMain(), kCFRunLoopDefaultMode))
{
returnValue = YES;
}
}
return returnValue;
xxx.m
ReachabilityCallback {
//do something when network change
}
我测试将移动(4G)更改为wifi1
接到电话
Status4G
StatusNone
StatusWifi1
当将 wifi1 更改为 wifi2 时
StatusWifi1
StatusNone
StatusWifi2
但是,有时,当 wifi 变化非常快并且没有变为 时StatusNone
,当我将 wifi1 更改为 wifi2 或相反时,我没有收到回调。
我想要得到的是
StatusWifi1
StatusWifi2
-------------------------UPDATE----------------------------
谢谢@Hitesh Surani,现在我的问题有时在某些设备上,我没有收到disconnect state
,我尝试使用
[self reachabilityWithAddress: @"www.google.com"]
代替
[self reachabilityWithAddress: (const struct sockaddr *) &zeroAddress]
现在,当 wifi 改变时我可以收到回电,即使它没有变成disconnect state
,但我仍然不知道为什么,这里是状态改变:
//wifi1:
1 kSCNetworkReachabilityFlagsReachable
//wifi1 -> wifi2
2 kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsTransientConnection
3 kSCNetworkReachabilityFlagsReachable
当更改 wifi 时,有 tmp 状态kSCNetworkReachabilityFlagsReachable | kSCNetworkReachabilityFlagsTransientConnection
,这就是为什么我可以检测到 wifi 更改,但这是什么kSCNetworkReachabilityFlagsTransientConnection
意思?我阅读了Apple的文档,仍然感到困惑。
解决方案
感谢您提出很好的问题。
主要Reachability
是用于跟踪互联网连接变化的类。没有检测 wifi 更改通知的规定。所以在一个词类中Reachability
不提供这种类型的功能。如果你想达到你的要求,那么下面需要定制。
您可以实现如下所示的 wifi 更改通知。
当您的 wifi 连接更改或切换到任何其他网络时,您会在几分之一秒内收到断开连接状态。所以
reachabilityChanged
方法被调用。通过使用以下代码,您可以获得 wifi 信息,例如 BSSID、SSID(Name) 和 SSID 数据。只需将wifi信息存储到本地即可。
- 当网络发生变化时,您可以检查新的 wifi 信息是否与前一个匹配。如果没有,则用户连接新的 wifi。
将以下代码放入reachabilityChanged
方法中。
import SystemConfiguration.CaptiveNetwork
func printCurrentWifiInfo() {
if let interface = CNCopySupportedInterfaces() {
for i in 0..<CFArrayGetCount(interface) {
let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interface, i)
let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
if let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)" as CFString), let interfaceData = unsafeInterfaceData as? [String : AnyObject] {
// connected wifi
print("BSSID: \(String(describing: interfaceData["BSSID"])), SSID: \(String(describing: interfaceData["SSID"])), SSIDDATA: \(String(describing: interfaceData["SSIDDATA"]))")
} else {
//Wifi is not connected
}
}
}
}
更新:
Apple 提供com.apple.system.config.network_change
收听 wifi 更改通知。基本上它是Core Foundation
框架的一部分。我相信它会为你工作。
请添加以下代码以收听 wifi 更改。
let notificationName = "com.apple.system.config.network_change"
func onNetworkChange(_ name : String) {
if (name == notificationName) {
// Do your stuff
print("Network was changed")
}
}
func registerObserver() {
let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer,
{ (nc, observer, name, _, _) -> Swift.Void in
if let observer = observer, let name = name {
let instance = Unmanaged<Reachability>.fromOpaque(observer).takeUnretainedValue()
instance.onNetworkChange(name.rawValue as String)
} },
notificationName as CFString, nil, .deliverImmediately)
}
func removeObserver() {
let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer, nil, nil)
}
在 init 上注册观察者并在 deinit 上删除。从这里 找到参考。
推荐阅读
- python - 如何在 python 中生成一个 12 位长的随机数?
- java - 如何在 Apache poi SXSSFWorkbook 上添加自定义 SheetDataWriter?
- jquery - 在 jquery 中访问另一个父级的子元素
- javascript - 图像在 chrome 中加载一半
- python - ORM:发票。什么是 v10 中的 register_payment 的 v14 等价物?
- ios - 在 iOS 的 FirebaseUI 中,强制使用深色模式会导致 Apple 图标与背景融为一体
- python - 为什么使用 Python 调用 Bash 脚本时返回 256
- javascript - 在 rateYo jquery star 插件上显示默认星级
- sharepoint - 我可以拥有的 Sharepoint 搜索 API 结果的最大大小是多少?
- javascript - 如何使用 react-router-dom 防止浏览器返回并保持状态