iOS开发-Reachability实时检测Wifi,2G/3G/4G/网络状态

简介:

最近遇到一个功能就是根据用户当前的网络状,用户未联网需要提示一下,如果是Wifi可以推荐一些图片新闻,如果是3G模式设置为无图的模式,获取网络状态比较简单,毕竟中国现在的流量还是一个比较贵的状态,哪天用户发现App消耗流量过多说不定就干掉了App不过苹果的Reachability都解决了以上问题,使用起来也比较方便,具体的稍微简单分析一下。

Reachability.h头文件代码:

 

 

Reachability.m文件:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <sys/socket.h>
#import <CoreFoundation/CoreFoundation.h>
#import "Reachability.h"
 
 
NSString  *kReachabilityChangedNotification = @ "kNetworkReachabilityChangedNotification" ;
 
 
#pragma mark - Supporting functions
 
#define kShouldPrintReachabilityFlags 1
 
static  void  PrintReachabilityFlags(SCNetworkReachabilityFlags flags,  const  char * comment)
{
#if kShouldPrintReachabilityFlags
 
     NSLog (@ "Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n" ,
           //当前网络2G/3G/4G蜂窝网络
           (flags & kSCNetworkReachabilityFlagsIsWWAN)               ?  'W'  '-' ,
           //网络是否可达
           (flags & kSCNetworkReachabilityFlagsReachable)            ?  'R'  '-' ,
 
           (flags & kSCNetworkReachabilityFlagsTransientConnection)  ?  't'  '-' ,
           (flags & kSCNetworkReachabilityFlagsConnectionRequired)   ?  'c'  '-' ,
           (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ?  'C'  '-' ,
           (flags & kSCNetworkReachabilityFlagsInterventionRequired) ?  'i'  '-' ,
           (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ?  'D'  '-' ,
           (flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ?  'l'  '-' ,
           (flags & kSCNetworkReachabilityFlagsIsDirect)             ?  'd'  '-' ,
           comment
           );
#endif
}
 
 
static  void  ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags,  void * info)
{
#pragma unused (target, flags)
     NSCAssert (info !=  NULL , @ "info was NULL in ReachabilityCallback" );
     NSCAssert ([(__bridge  NSObject *) info isKindOfClass: [Reachability  class ]], @ "info was wrong class in ReachabilityCallback" );
     //http://www.cnblogs.com/xiaofeixiang
     Reachability* noteObject = (__bridge Reachability *)info;
     // Post a notification to notify the client that the network reachability changed.
     [[ NSNotificationCenter  defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
}
 
 
#pragma mark - Reachability implementation
 
@implementation  Reachability
{
     BOOL  _alwaysReturnLocalWiFiStatus;  //default is NO
     SCNetworkReachabilityRef _reachabilityRef;
}
//通过域名进行实例化  博客园-Fly_Elephant
+ (instancetype)reachabilityWithHostName:( NSString  *)hostName
{
     Reachability* returnValue =  NULL ;
     SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName( NULL , [hostName UTF8String]);
     if  (reachability !=  NULL )
     {
         returnValue= [[ self  alloc] init];
         if  (returnValue !=  NULL )
         {
             returnValue->_reachabilityRef = reachability;
             returnValue->_alwaysReturnLocalWiFiStatus =  NO ;
         }
     }
     return  returnValue;
}
 
//通过ip地址实例化Reachability
+ (instancetype)reachabilityWithAddress:( const  struct  sockaddr_in *)hostAddress
{
     SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, ( const  struct  sockaddr *)hostAddress);
 
     Reachability* returnValue =  NULL ;
 
     if  (reachability !=  NULL )
     {
         returnValue = [[ self  alloc] init];
         if  (returnValue !=  NULL )
         {
             returnValue->_reachabilityRef = reachability;
             returnValue->_alwaysReturnLocalWiFiStatus =  NO ;
         }
     }
     return  returnValue;
}
 
 
//检测是否能够直接连上互联网
+ (instancetype)reachabilityForInternetConnection
{
     struct  sockaddr_in zeroAddress;
     bzero(&zeroAddress,  sizeof (zeroAddress));
     zeroAddress.sin_len =  sizeof (zeroAddress);
     zeroAddress.sin_family = AF_INET;
     
     return  [ self  reachabilityWithAddress:&zeroAddress];
}
 
//检测当前网络是否能够联上wifi
+ (instancetype)reachabilityForLocalWiFi
{
     struct  sockaddr_in localWifiAddress;
     bzero(&localWifiAddress,  sizeof (localWifiAddress));
     localWifiAddress.sin_len =  sizeof (localWifiAddress);
     localWifiAddress.sin_family = AF_INET;
 
     // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0.
     localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
 
     Reachability* returnValue = [ self  reachabilityWithAddress: &localWifiAddress];
     if  (returnValue !=  NULL )
     {
         returnValue->_alwaysReturnLocalWiFiStatus =  YES ;
     }
     
     return  returnValue;
}
 
 
#pragma mark - Start and stop notifier
 
- ( BOOL )startNotifier
{
     BOOL  returnValue =  NO ;
 
     SCNetworkReachabilityContext context = {0, (__bridge  void  *)( self ),  NULL NULL NULL };
     //SCNetworkReachabilitySetCallback函数为指定一个target
     //当设备对于这个target链接状态发生改变时(比如断开链接,或者重新连上),则回调reachabilityCallback函数,
     if  (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
     {
         if  (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
         {
             returnValue =  YES ;
         }
     }
     
     return  returnValue;
}
 
 
- ( void )stopNotifier
{
     if  (_reachabilityRef !=  NULL )
     {
         SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
     }
}
 
 
- ( void )dealloc
{
     [ self  stopNotifier];
     if  (_reachabilityRef !=  NULL )
     {
         CFRelease(_reachabilityRef);
     }
}
 
 
#pragma mark - Network Flag Handling
 
- (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags
{
     PrintReachabilityFlags(flags,  "localWiFiStatusForFlags" );
     NetworkStatus returnValue = NotReachable;
 
     if  ((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
     {
         returnValue = ReachableViaWiFi;
     }
     
     return  returnValue;
}
 
 
- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
{
     PrintReachabilityFlags(flags,  "networkStatusForFlags" );
     if  ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
     {
         // The target host is not reachable.
         return  NotReachable;
     }
 
     NetworkStatus returnValue = NotReachable;
 
     if  ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
     {
         /*
          If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
          */
         returnValue = ReachableViaWiFi;
     }
 
     if  ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
         (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
     {
         /*
          ... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
          */
 
         if  ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
         {
             /*
              ... and no [user] intervention is needed...
              */
             returnValue = ReachableViaWiFi;
         }
     }
 
     if  ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
     {
         /*
          ... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
          */
         returnValue = ReachableViaWWAN;
     }
     
     return  returnValue;
}
 
 
- ( BOOL )connectionRequired
{
     NSAssert (_reachabilityRef !=  NULL , @ "connectionRequired called with NULL reachabilityRef" );
     SCNetworkReachabilityFlags flags;
 
     if  (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
     {
         return  (flags & kSCNetworkReachabilityFlagsConnectionRequired);
     }
 
     return  NO ;
}
 
//获取当前网络状态
- (NetworkStatus)currentReachabilityStatus
{
     NSAssert (_reachabilityRef !=  NULL , @ "currentNetworkStatus called with NULL SCNetworkReachabilityRef" );
     NetworkStatus returnValue = NotReachable;
     SCNetworkReachabilityFlags flags;
     
     if  (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
     {
         if  (_alwaysReturnLocalWiFiStatus)
         {
             returnValue = [ self  localWiFiStatusForFlags:flags];
         }
         else
         {
             returnValue = [ self  networkStatusForFlags:flags];
         }
     }
     
     return  returnValue;
}
 
 
@end

AppDelegate中的实现:

1
2
3
4
5
6
7
8
9
10
- ( BOOL )application:(UIApplication *)application didFinishLaunchingWithOptions:( NSDictionary  *)launchOptions {
     //添加一个系统通知
     [[ NSNotificationCenter  defaultCenter] addObserver: self  selector: @selector (reachabilityChanged:) name:kReachabilityChangedNotification object: nil ];
     //初始化
     self .internetReachability=[Reachability reachabilityForInternetConnection];
     //通知添加到Run Loop
     [ self .internetReachability startNotifier];
     [ self  updateInterfaceWithReachability:_internetReachability];
     return  YES ;
}

回调函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- ( void ) reachabilityChanged:( NSNotification  *)note
{
     Reachability* curReach = [note object];
     NSParameterAssert ([curReach isKindOfClass:[Reachability  class ]]);
     [ self  updateInterfaceWithReachability:curReach];
}
 
- ( void )updateInterfaceWithReachability:(Reachability *)reachability
{
     NetworkStatus netStatus = [reachability currentReachabilityStatus];
     switch  (netStatus) {
         case  NotReachable:
             NSLog (@ "====当前网络状态不可达=======http://www.cnblogs.com/xiaofeixiang" );
             break ;
         case  ReachableViaWiFi:
             NSLog (@ "====当前网络状态为Wifi=======博客园-Fly_Elephant" );
             break ;
         case  ReachableViaWWAN:
             NSLog (@ "====当前网络状态为3G=======keso" );
             break ;
     }
}

 模式测试 Wifi模式-wuWifi-连接Wifi,显示结果如下:

如果直接通过host实例化也可以:

1
2
NSString  *remoteHostName = @ "www.cnblogs.com/xiaofeixiang" ;
self .hostReachability = [Reachability reachabilityWithHostName:remoteHostName];  
本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4472343.html,如需转载请自行联系原作者
相关文章
|
8天前
|
计算机视觉 网络架构
【YOLOv8改进 - 卷积Conv】DWRSeg:扩张式残差分割网络,提高特征提取效率和多尺度信息获取能力,助力小目标检测
YOLO目标检测专栏探讨了YOLO的创新改进,如多尺度特征提取的DWRSeg网络。该网络通过区域残差化和语义残差化提升效率,使用DWR和SIR模块优化高层和低层特征。DWRSeg在Cityscapes和CamVid数据集上表现优秀,速度与准确性兼备。论文和代码已公开。核心代码展示了一个包含DWR模块的卷积层。更多配置详情见相关链接。
|
11天前
|
机器学习/深度学习 数据采集 前端开发
网络爬虫开发:JavaScript与Python特性的小差异
我们以前写JavaScript的代码时,在遇到了发送请求时,都是需要去await的。 但是为什么Python代码不需要这样做呢? 这就是因为JavaScript是异步的,Python是同步的。 JavaScript就需要使用关键词await将异步代码块变为同步代码。
|
26天前
|
机器学习/深度学习 算法 计算机视觉
基于深度学习网络的USB摄像头实时视频采集与人脸检测matlab仿真
**摘要 (Markdown格式):** ```markdown - 📹 使用USB摄像头(Tttttttttttttt666)实时视频检测,展示基于YOLOv2在MATLAB2022a的实施效果: ``` Tttttttttttttt1111111111------------5555555555 ``` - 📺 程序核心利用MATLAB视频采集配置及工具箱(Dddddddddddddd),实现图像采集与人脸定位。 - 🧠 YOLOv2算法概览:通过S×S网格预测边界框(B个/网格),含坐标、类别概率和置信度,高效检测人脸。
|
19天前
|
机器学习/深度学习 编解码 人工智能
一种基于YOLOv8改进的高精度表面缺陷检测网络, NEU-DET和GC10-DET涨点明显(原创自研)
【7月更文挑战第3天】一种基于YOLOv8改进的高精度表面缺陷检测, 在NEU-DET和GC10-DET任务中涨点明显;
42 1
|
5天前
|
机器学习/深度学习 算法 BI
基于深度学习网络的USB摄像头实时视频采集与手势检测识别matlab仿真
**摘要:** 本文介绍了使用MATLAB2022a实现的基于GoogLeNet的USB摄像头手势识别系统。系统通过摄像头捕获视频,利用深度学习的卷积神经网络进行手势检测与识别。GoogLeNet网络的Inception模块优化了计算效率,避免过拟合。手势检测涉及RPN生成候选框,送入网络进行分类。系统架构包括视频采集、手势检测与识别、以及决策反馈。通过GPU加速和模型优化保证实时性能,应用于智能家居等场景。
|
1月前
|
监控 5G
GPRS与4G网络:技术差异与应用选择
GPRS与4G在移动通信中各有重要地位,但4G(如LTE)以其高达1Gbps的速度、低延迟及优化的高带宽应用(如视频监控)超越了GPRS的几十Kbps速度。5G的兴起将进一步革新通信,带来更快、更智能的服务。选择技术需依据实际需求。
|
16天前
|
数据采集 Perl
错误处理在网络爬虫开发中的重要性:Perl示例 引言
错误处理在网络爬虫开发中的重要性:Perl示例 引言
|
1月前
|
机器学习/深度学习
【从零开始学习深度学习】21. 卷积神经网络(CNN)之二维卷积层原理介绍、如何用卷积层检测物体边缘
【从零开始学习深度学习】21. 卷积神经网络(CNN)之二维卷积层原理介绍、如何用卷积层检测物体边缘
|
29天前
|
数据采集 JavaScript 前端开发
使用Colly库进行高效的网络爬虫开发
使用Colly库进行高效的网络爬虫开发
|
29天前
|
文字识别 开发工具 Android开发
视觉智能开放平台操作报错合集之使用人脸属性检测接口,出现报错:图片无法下载,请检查链接是否可访问和本地网络情况,该如何解决
在使用视觉智能开放平台时,可能会遇到各种错误和问题。虽然具体的错误代码和消息会因平台而异,但以下是一些常见错误类型及其可能的原因和解决策略的概述,包括但不限于:1. 认证错误、2. 请求参数错误、3. 资源超限、4. 图像质量问题、5. 服务不可用、6. 模型不支持的场景、7. 网络连接问题,这有助于快速定位和解决问题。