欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS实现实时检测网络状态的示例代码

程序员文章站 2023-12-21 14:28:16
前言 在网络应用中,需要对用户设备的网络状态进行实时监控,有两个目的: (1)让用户了解自己的网络状态,防止一些误会(比如怪应用无能) (2)根据用户的网络状态进行智...

前言

在网络应用中,需要对用户设备的网络状态进行实时监控,有两个目的:

(1)让用户了解自己的网络状态,防止一些误会(比如怪应用无能)

(2)根据用户的网络状态进行智能处理,节省用户流量,提高用户体验

  wifi\3g网络:自动下载高清图片

  低速网络:只下载缩略图

  没有网络:只显示离线的缓存数据

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

示例代码

reachability.h头文件代码:

#import <foundation/foundation.h> 
#import <systemconfiguration/systemconfiguration.h> 
#import <netinet/in.h> 
 
//http://www.cnblogs.com/xiaofeixiang 
typedef enum : nsinteger { 
 notreachable = 0, 
 reachableviawifi, 
 reachableviawwan 
} networkstatus; 
 
 
extern nsstring *kreachabilitychangednotification; 
 
 
@interface reachability : nsobject 
 
/*! 
 * use to check the reachability of a given host name. 
 */ 
+ (instancetype)reachabilitywithhostname:(nsstring *)hostname; 
 
/*! 
 * use to check the reachability of a given ip address. 
 */ 
+ (instancetype)reachabilitywithaddress:(const struct sockaddr_in *)hostaddress; 
 
/*! 
 * checks whether the default route is available. should be used by applications that do not connect to a particular host. 
 */ 
+ (instancetype)reachabilityforinternetconnection; 
 
/*! 
 * checks whether a local wifi connection is available. 
 */ 
+ (instancetype)reachabilityforlocalwifi; 
 
/*! 
 * start listening for reachability notifications on the current run loop. 
 */ 
- (bool)startnotifier; 
- (void)stopnotifier; 
 
- (networkstatus)currentreachabilitystatus; 
 
/*! 
 * wwan may be available, but not active until a connection has been established. wifi may require a connection for vpn on demand. 
 */ 
- (bool)connectionrequired; 
 
@end

reachability.m文件:

#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 voidvoid *)(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中的实现:

- (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; 
} 

回调函数:

(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; 
 } 
} 

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。

上一篇:

下一篇: