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,如需转载请自行联系原作者
相关文章
|
3月前
|
Linux 开发工具 Android开发
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
ijkplayer是由Bilibili基于FFmpeg3.4研发并开源的播放器,适用于Android和iOS,支持本地视频及网络流媒体播放。本文详细介绍如何在新版Android Studio中导入并使用ijkplayer库,包括Gradle版本及配置更新、导入编译好的so文件以及添加直播链接播放代码等步骤,帮助开发者顺利进行App调试与开发。更多FFmpeg开发知识可参考《FFmpeg开发实战:从零基础到短视频上线》。
246 2
FFmpeg开发笔记(六十)使用国产的ijkplayer播放器观看网络视频
|
15天前
|
运维 监控 安全
公司监控软件:SAS 数据分析引擎驱动网络异常精准检测
在数字化商业环境中,企业网络系统面临复杂威胁。SAS 数据分析引擎凭借高效处理能力,成为网络异常检测的关键技术。通过统计分析、时间序列分析等方法,SAS 帮助企业及时发现并处理异常流量,确保网络安全和业务连续性。
39 11
|
2月前
|
API
鸿蒙开发:切换至基于rcp的网络请求
本文的内容主要是把之前基于http封装的库,修改为当前的Remote Communication Kit(远场通信服务),无非就是通信的方式变了,其他都大差不差。
鸿蒙开发:切换至基于rcp的网络请求
|
2月前
|
存储 网络协议 物联网
C 语言物联网开发之网络通信与数据传输难题
本文探讨了C语言在物联网开发中遇到的网络通信与数据传输挑战,分析了常见问题并提出了优化策略,旨在提高数据传输效率和系统稳定性。
|
2月前
|
机器学习/深度学习 计算机视觉 网络架构
【YOLO11改进 - C3k2融合】C3k2DWRSeg二次创新C3k2_DWR:扩张式残差分割网络,提高特征提取效率和多尺度信息获取能力,助力小目标检测
【YOLO11改进 - C3k2融合】C3k2DWRSeg二次创新C3k2_DWR:扩张式残差分割网络,提高特征提取效率和多尺度信息获取能力,助力小目DWRSeg是一种高效的实时语义分割网络,通过将多尺度特征提取分为区域残差化和语义残差化两步,提高了特征提取效率。它引入了Dilation-wise Residual (DWR) 和 Simple Inverted Residual (SIR) 模块,优化了不同网络阶段的感受野。在Cityscapes和CamVid数据集上的实验表明,DWRSeg在准确性和推理速度之间取得了最佳平衡,达到了72.7%的mIoU,每秒319.5帧。代码和模型已公开。
【YOLO11改进 - C3k2融合】C3k2DWRSeg二次创新C3k2_DWR:扩张式残差分割网络,提高特征提取效率和多尺度信息获取能力,助力小目标检测
|
2月前
|
安全 Linux 网络安全
nmap 是一款强大的开源网络扫描工具,能检测目标的开放端口、服务类型和操作系统等信息
nmap 是一款强大的开源网络扫描工具,能检测目标的开放端口、服务类型和操作系统等信息。本文分三部分介绍 nmap:基本原理、使用方法及技巧、实际应用及案例分析。通过学习 nmap,您可以更好地了解网络拓扑和安全状况,提升网络安全管理和渗透测试能力。
163 5
|
2月前
|
机器学习/深度学习 搜索推荐 安全
深度学习之社交网络中的社区检测
在社交网络分析中,社区检测是一项核心任务,旨在将网络中的节点(用户)划分为具有高内部连接密度且相对独立的子群。基于深度学习的社区检测方法,通过捕获复杂的网络结构信息和节点特征,在传统方法基础上实现了更准确、更具鲁棒性的社区划分。
79 7
|
3月前
|
XML 开发工具 Android开发
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
ExoPlayer最初是为了解决Android早期MediaPlayer控件对网络视频兼容性差的问题而推出的。现在,Android官方已将其升级并纳入Jetpack的Media3库,使其成为音视频操作的统一引擎。新版ExoPlayer支持多种协议,解决了设备和系统碎片化问题,可在整个Android生态中一致运行。通过修改`build.gradle`文件、布局文件及Activity代码,并添加必要的权限,即可集成并使用ExoPlayer进行网络视频播放。具体步骤包括引入依赖库、配置播放界面、编写播放逻辑以及添加互联网访问权限。
194 1
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
|
2月前
|
机器学习/深度学习 计算机视觉 网络架构
【YOLO11改进 - C3k2融合】C3k2融合DWRSeg二次创新C3k2_DWRSeg:扩张式残差分割网络,提高特征提取效率和多尺度信息获取能力,助力小目标检测
【YOLO11改进 - C3k2融合】C3k2融合DWRSDWRSeg是一种高效的实时语义分割网络,通过将多尺度特征提取方法分解为区域残差化和语义残差化两步,提高了多尺度信息获取的效率。网络设计了Dilation-wise Residual (DWR) 和 Simple Inverted Residual (SIR) 模块,分别用于高阶段和低阶段,以充分利用不同感受野的特征图。实验结果表明,DWRSeg在Cityscapes和CamVid数据集上表现出色,以每秒319.5帧的速度在NVIDIA GeForce GTX 1080 Ti上达到72.7%的mIoU,超越了现有方法。代码和模型已公开。
|
3月前
|
运维 安全 网络协议
Python 网络编程:端口检测与IP解析
本文介绍了使用Python进行网络编程的两个重要技能:检查端口状态和根据IP地址解析主机名。通过`socket`库实现端口扫描和主机名解析的功能,并提供了详细的示例代码。文章最后还展示了如何整合这两部分代码,实现一个简单的命令行端口扫描器,适用于网络故障排查和安全审计。
58 0

热门文章

最新文章