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,如需转载请自行联系原作者
相关文章
|
10天前
|
C++
C++ Qt开发:QUdpSocket网络通信组件
QUdpSocket是Qt网络编程中一个非常有用的组件,它提供了在UDP协议下进行数据发送和接收的能力。通过简单的方法和信号,可以轻松实现基于UDP的网络通信。不过,需要注意的是,UDP协议本身不保证数据的可靠传输,因此在使用QUdpSocket时,可能需要在应用层实现一些机制来保证数据的完整性和顺序,或者选择在适用的场景下使用UDP协议。
43 2
|
9天前
|
小程序 数据安全/隐私保护
Taro@3.x+Vue@3.x+TS开发微信小程序,网络请求封装
在 `src/http` 目录下创建 `request.ts` 文件,并配置 Taro 的网络请求方法 `Taro.request`,支持多种 HTTP 方法并处理数据加密。
Taro@3.x+Vue@3.x+TS开发微信小程序,网络请求封装
|
10天前
|
计算机视觉
在yolov5项目中如何使用自带摄像机不用网络摄像机进行实时检测?
这篇文章讨论了在yolov5项目中,如何避免使用网络摄像机而改用自带的本地摄像机进行实时目标检测,并提供了解决摄像头打开错误的具体步骤和代码示例。
在yolov5项目中如何使用自带摄像机不用网络摄像机进行实时检测?
|
17天前
|
数据采集 存储 前端开发
豆瓣评分9.0!Python3网络爬虫开发实战,堪称教学典范!
今天我们所处的时代是信息化时代,是数据驱动的人工智能时代。在人工智能、物联网时代,万物互联和物理世界的全面数字化使得人工智能可以基于这些数据产生优质的决策,从而对人类的生产生活产生巨大价值。 在这个以数据驱动为特征的时代,数据是最基础的。数据既可以通过研发产品获得,也可以通过爬虫采集公开数据获得,因此爬虫技术在这个快速发展的时代就显得尤为重要,高端爬虫人才的收人也在逐年提高。
|
7天前
|
机器学习/深度学习 运维 监控
|
7天前
|
UED 存储 数据管理
深度解析 Uno Platform 离线状态处理技巧:从网络检测到本地存储同步,全方位提升跨平台应用在无网环境下的用户体验与数据管理策略
【8月更文挑战第31天】处理离线状态下的用户体验是现代应用开发的关键。本文通过在线笔记应用案例,介绍如何使用 Uno Platform 优雅地应对离线状态。首先,利用 `NetworkInformation` 类检测网络状态;其次,使用 SQLite 实现离线存储;然后,在网络恢复时同步数据;最后,通过 UI 反馈提升用户体验。
15 0
|
8天前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享安卓与iOS开发中的线程管理比较
【8月更文挑战第30天】本文将探讨网络安全与信息安全的重要性,并分享关于网络安全漏洞、加密技术和安全意识的知识。我们将了解常见的网络攻击类型和防御策略,以及如何通过加密技术和提高安全意识来保护个人和组织的信息安全。
|
9天前
|
安全 网络安全 Android开发
探索安卓开发之旅:从新手到专家网络安全与信息安全:防范网络威胁,保护数据安全
【8月更文挑战第29天】在这篇技术性文章中,我们将踏上一段激动人心的旅程,探索安卓开发的世界。无论你是刚开始接触编程的新手,还是希望提升技能的资深开发者,这篇文章都将为你提供宝贵的知识和指导。我们将从基础概念入手,逐步深入到安卓开发的高级主题,包括UI设计、数据存储、网络通信等方面。通过阅读本文,你将获得一个全面的安卓开发知识体系,并学会如何将这些知识应用到实际项目中。让我们一起开启这段探索之旅吧!
|
17天前
|
JSON 监控 安全
在Linux中,如何使用Suricata进行实时网络威胁检测?
在Linux中,如何使用Suricata进行实时网络威胁检测?
|
1天前
|
存储 安全 网络安全
云计算与网络安全:云服务、网络安全、信息安全等技术领域的探讨
【9月更文挑战第5天】云计算作为一种新兴的计算模式,已经在全球范围内得到了广泛的应用。然而,随着云计算的快速发展,网络安全问题也日益凸显。本文将从云服务、网络安全、信息安全等方面对云计算与网络安全进行探讨。
26 15
下一篇
DDNS