最近做了一个在 iOS 平台下提示用户网络异常的功能,许久没有做 iOS 原生需求了,接手这个需求后感觉 iOS 的坑也越来越多了。
这种需求很常见,首先分析一下这里指的网络异常包括,飞行模式、Wi-Fi 和蜂窝网络都被关闭、Wi-Fi 连接状态下应用的 Wi-Fi 权限被关闭,只有蜂窝连接的情况下应用蜂窝权限被关闭。
对这些情况的处理里程图如下:
下面把整个流程中的实现方法和需要注意的坑讲一下。
判断是否飞行模式
1 2 3 4 5 6 7 8 9 10
| #import <CoreTelephony/CTTelephonyNetworkInfo.h>
/* 判断是否飞行模式 */ + (BOOL)isAirPlaneMode { CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init]; return (BOOL)!networkInfo.currentRadioAccessTechnology; }
|
如果 networkInfo.currentRadioAccessTechnology
返回 nil
则可以判断处于飞行模式。
判断 Wi-Fi 是否打开
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #import <ifaddrs.h> #import <net/if.h>
/* Wifi开关是否打开 */ + (BOOL) isWiFiEnabled { NSString *const WIFI_INTERFACE_NAME = @"awdl0"; NSCountedSet * cset = [NSCountedSet new]; struct ifaddrs *interfaces; if(!getifaddrs(&interfaces)) { for( struct ifaddrs *interface = interfaces; interface; interface = interface->ifa_next) { if ( (interface->ifa_flags & IFF_UP) == IFF_UP ) { [cset addObject:[NSString stringWithUTF8String:interface->ifa_name]]; } } } return [cset countForObject:WIFI_INTERFACE_NAME] > 1 ? YES : NO; }
|
awdl0
是 wifi interface 的名称,判断是否有这个名称的 interface
就知道是否有打开 wifi 开关。
判断是否有 Wi-Fi 权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #import <SystemConfiguration/CaptiveNetwork.h>
/* 判断是否禁用了 Wi-Fi 权限 */ + (BOOL) isWifiNetWorkRestricted { NSArray *ifs = (__bridge_transfer NSArray *)CNCopySupportedInterfaces(); if (!ifs) { return nil; } NSDictionary *info = nil; for (NSString *ifnam in ifs) { info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam); if (info && [info count]) { break; } } return (BOOL)info; }
|
如果 Wi-Fi 开关已经打开且 info 是 nil
那么就可以判断没有 Wi-Fi 权限。
判断是否有蜂窝网络权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #import <CoreTelephony/CTCellularData.h>
if ([GlobalUtils systemVersion] >= 9.0) { // iOS系统版本 >= 9.0 CTCellularData *cellularData = [[CTCellularData alloc] init]; cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state){ //获取联网状态 switch (state) { case kCTCellularDataRestricted: // 蜂窝网络受限,提示用户 ... break; case kCTCellularDataNotRestricted: // 有访问蜂窝网络的权限,说明蜂窝数据的开关被关闭了 ... break; case kCTCellularDataRestrictedStateUnknown: // 从来没有过网络访问的时候会是这个状态 // 异常情况 ... break; default: break; }; }; } else { // 异常情况 }
|
坑
- 国行版本的 iPhone 存在 Wi-Fi 权限的开关但是其他版本的 iPhone 不存在这个开关。
- iOS 10 以上版本的操作系统不允许第三方 App 跳转到系统设置页面,只允许他们跳转到 App 自己的设置页。
- 国行版本的 iPhone 在蜂窝和 Wi-Fi 关闭的情况下可以设置应用的 Wi-Fi 和蜂窝的权限,而其他版本不可以。
- 无法知道蜂窝开关是否打开,只能知道有无权限,非国行版本的 iPhone 在蜂窝被关闭的情况下无法打开蜂窝权限,所以要特殊处理,iOS10.0 以下的版本跳转到系统的蜂窝移动网络设置页面,10.0 以上的版本不做跳转。
参见
iOS中判断网络的状态的几种方法
iOS,利用URL Schemes跳转到设置wifi、蜂窝移动网络页面
iOS Settings URL Scheme