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