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,如需转载请自行联系原作者
相关文章
|
4天前
|
开发工具 Android开发 iOS开发
探索Android与iOS开发的差异与挑战
【7月更文挑战第11天】在移动应用开发的广阔天地中,Android和iOS两大平台如同双子星座般耀眼,各自拥有独特的开发生态和用户群体。本文将深入分析这两个平台的显著差异,从技术架构到开发工具,再到市场定位,揭示它们之间的异同。通过比较,我们不仅能够更好地理解各自的优势和局限,还能洞察未来移动应用开发的趋势。
|
7天前
|
Java Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【7月更文挑战第8天】在移动应用开发的广阔天地中,Android与iOS两大平台各自占据着半壁江山。本文将深入探讨这两个平台在开发环境、用户界面设计、性能优化以及市场覆盖等方面的根本差异,并分析这些差异如何影响项目的成功。通过比较和分析,旨在为开发者在选择平台时提供更全面的视角,帮助他们根据项目需求和目标市场做出更明智的决策。
|
2天前
|
前端开发 开发工具 Swift
学习iOS开发的准备
准备学习iOS开发?确保有Mac和最新Xcode,先学好编程基础特别是Swift。利用Apple官方文档、在线课程和书籍作为资源。熟悉Xcode及Git,通过实践项目和开源代码积累经验。深研架构模式、核心框架和优化技巧。加入开发者社区,关注行业动态,持续学习。
14 1
|
8天前
|
开发工具 Swift iOS开发
探索iOS开发中的SwiftUI框架
【7月更文挑战第7天】在iOS应用开发的广阔天地中,SwiftUI框架以其现代化的设计理念和强大的功能特性,正逐步改变着开发者构建用户界面的方式。本文将深入探讨SwiftUI的核心概念、优势以及在实际项目中的应用,帮助读者理解这一框架如何简化iOS开发流程并提升用户体验。
187 7
|
7天前
|
移动开发 开发工具 Android开发
探索安卓与iOS开发的差异:平台特性与编程实践
【7月更文挑战第8天】在移动开发的广阔天地中,安卓和iOS这两大操作系统各自占据着半壁江山。它们在用户界面设计、系统架构及开发工具上展现出截然不同的特色。本文将深入探讨这两个平台在技术实现和开发生态上的关键差异,并分享一些实用的开发技巧,旨在为跨平台开发者提供有价值的见解和建议。
|
4天前
|
Java 开发工具 Android开发
探索Android与iOS开发的差异与挑战
【7月更文挑战第11天】在移动应用开发的广阔天地中,Android和iOS两大平台各领风骚。本文将深入探讨这两个平台的开发差异,从编程语言、用户界面设计到开发工具等方面进行比较,并分析开发者面临的挑战。通过对比分析,旨在为开发者提供一个全面的视角,帮助他们更好地选择适合自己项目需求的开发平台。
8 0
|
4天前
|
iOS开发 开发者 UED
探索iOS开发中的SwiftUI框架
【7月更文挑战第11天】本文将深入探讨SwiftUI框架,这是苹果公司为iOS开发者提供的一个现代化、声明式的用户界面工具。我们将了解SwiftUI如何简化界面设计流程,提升代码的可读性和可维护性,并讨论其在实际应用中的优势和局限性。通过实际案例分析,本文旨在帮助读者更好地理解SwiftUI的核心概念和应用实践。
|
5天前
|
机器学习/深度学习 人工智能 iOS开发
探索iOS开发的未来:SwiftUI的革新之旅
在数字时代的浪潮中,iOS开发正经历一场由SwiftUI引领的变革。本文将深入探讨SwiftUI如何重塑移动应用开发,提升开发者的生产力,并展望其对iOS生态的影响。通过分析SwiftUI的核心特性、实际案例和未来趋势,我们将揭示这一现代框架如何定义用户体验的新标准,同时为iOS开发者指明技术进阶之路。
|
6天前
|
搜索推荐 Android开发 iOS开发
探索Android与iOS开发的差异:平台特性与用户体验的对比分析
【7月更文挑战第9天】在移动应用开发的浩瀚海洋中,Android和iOS两大操作系统如同两座灯塔,指引着开发者们的航向。本文将深入探讨这两个平台在开发环境、用户界面设计、性能优化以及市场策略上的根本差异。我们将通过比较分析,揭示各自平台的独特优势和潜在挑战,为开发者提供决策支持,同时也为用户体验的提升指明方向。
|
10天前
|
移动开发 Android开发 iOS开发
探索安卓与iOS开发的差异:平台选择对应用性能的影响
在移动开发的广阔舞台上,安卓与iOS这两大操作系统各据一方,引领着技术潮流与市场需求。本文深入探讨了这两个平台在开发过程中的关键差异,并分析了这些差异如何影响应用的性能和用户体验。通过对比分析,我们将揭示开发者在选择平台时应考虑的技术细节,以及这些选择如何塑造最终产品的命运。文章不仅为开发者提供了实用的指导,也为那些对移动开发感兴趣的读者提供了深刻的洞见。