关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节
由于设计的游戏需要有一些联网请求,但有时候在设备未连接网络的情况下,如果对网络情况不加以判断,则可能造成游戏为了等游戏超时,浪费不必要的时间。
所以在游戏启动时检测一下网络状况是很必要的,而且当玩家的设备连接上网络以后,有一个回调函数也是非常必要的一件事儿,这样可能更方便我们在后台下载数据库等信息。
apple为我们提供了一套范例代码,下面我就来分析一下这段代码。
范例代码地址在:https://developer.apple.com/library/ios/#samplecode/Reachability/Listings/Classes_ReachabilityAppDelegate_m.html#//apple_ref/doc/uid/DTS40007324-Classes_ReachabilityAppDelegate_m-DontLinkElementID_4
范例中包含两部分,一部分是appdelegate,一部分是reachability
- #import <sys/socket.h>
- #import <netinet/in.h>
- #import <netinet6/in6.h>
- #import <arpa/inet.h>
- #import <ifaddrs.h>
- #import <netdb.h>
- #import <CoreFoundation/CoreFoundation.h>
- #import "Reachability.h"
- #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",
- (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',//当前网络为蜂窝网络,即3G或者GPRS
- (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
- }
- @implementation Reachability
- static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
- {
- #pragma unused (target, flags)
- NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
- NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
- //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
- // in case someon uses the Reachablity object in a different thread.
- NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
- Reachability* noteObject = (Reachability*) info;
- // Post a notification to notify the client that the network reachability changed.
- [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
- [myPool release];
- }
- //启动探测网络
- - (BOOL) startNotifier
- {
- BOOL retVal = NO;
- SCNetworkReachabilityContext context = {, self, NULL, NULL, NULL};
- //SCNetworkReachabilitySetCallback函数为指定一个target(此处为reachabilityRef,即www.apple.com,在reachabilityWithHostName里设置的)
- //当设备对于这个target链接状态发生改变时(比如断开链接,或者重新连上),则回调reachabilityCallback函数,
- if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
- {
- //指定一个runloop给指定的target
- if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
- {
- retVal = YES;
- }
- }
- return retVal;
- }
- //停止网络探测
- - (void) stopNotifier
- {
- if(reachabilityRef!= NULL)
- {
- SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
- }
- }
- - (void) dealloc
- {
- [self stopNotifier];
- if(reachabilityRef!= NULL)
- {
- CFRelease(reachabilityRef);
- }
- [super dealloc];
- }
- //通过域名设定一个目标地址比如www.apple.com
- + (Reachability*) reachabilityWithHostName: (NSString*) hostName;
- {
- Reachability* retVal = NULL;
- SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
- if(reachability!= NULL)
- {
- retVal= [[[self alloc] init] autorelease];
- if(retVal!= NULL)
- {
- retVal->reachabilityRef = reachability;
- retVal->localWiFiRef = NO;
- }
- }
- return retVal;
- }
- //通过ip地址设定一个目标的地址,可以加端口号,貌似我实验的不太成功
- + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
- {
- SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
- Reachability* retVal = NULL;
- if(reachability!= NULL)
- {
- retVal= [[[self alloc] init] autorelease];
- if(retVal!= NULL)
- {
- retVal->reachabilityRef = reachability;
- retVal->localWiFiRef = NO;
- }
- }
- return retVal;
- }
- //检测当前网络能否连上internet
- + (Reachability*) reachabilityForInternetConnection;
- {
- struct sockaddr_in zeroAddress;
- bzero(&zeroAddress, sizeof(zeroAddress));
- zeroAddress.sin_len = sizeof(zeroAddress);
- zeroAddress.sin_family = AF_INET;
- return [self reachabilityWithAddress: &zeroAddress];
- }
- //检测当前网络是否能够连上本地wifi
- + (Reachability*) 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* retVal = [self reachabilityWithAddress: &localWifiAddress];
- if(retVal!= NULL)
- {
- retVal->localWiFiRef = YES;
- }
- return retVal;
- }
- #pragma mark Network Flag Handling
- - (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags
- {
- PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
- BOOL retVal = NotReachable;
- if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
- {
- retVal = ReachableViaWiFi;
- }
- return retVal;
- }
- //通过flags返回当前网络状态
- - (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags
- {
- PrintReachabilityFlags(flags, "networkStatusForFlags");
- if ((flags & kSCNetworkReachabilityFlagsReachable) == )
- {
- // if target host is not reachable
- return NotReachable;
- }
- BOOL retVal = NotReachable;
- if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == )
- {
- // if target host is reachable and no connection is required
- // then we'll assume (for now) that your on Wi-Fi
- retVal = ReachableViaWiFi;
- }
- if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != ) ||
- (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != ))
- {
- // ... and the connection is on-demand (or on-traffic) if the
- // calling application is using the CFSocketStream or higher APIs
- if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == )
- {
- // ... and no [user] intervention is needed
- retVal = ReachableViaWiFi;
- }
- }
- if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
- {
- // ... but WWAN connections are OK if the calling application
- // is using the CFNetwork (CFSocketStream?) APIs.
- retVal = ReachableViaWWAN;
- }
- return retVal;
- }
- - (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 reachabilityRef");
- NetworkStatus retVal = NotReachable;
- SCNetworkReachabilityFlags flags;
- if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
- {
- if(localWiFiRef)
- {
- retVal = [self localWiFiStatusForFlags: flags];
- }
- else
- {
- retVal = [self networkStatusForFlags: flags];
- }
- }
- return retVal;
- }
- @end
以上的部分为具体实现的部分,下面我们再来看在appdelegate里面调用的部分
- - (void) applicationDidFinishLaunching: (UIApplication* )application
- {
- #pragma unused(application)
- contentView.backgroundColor = [UIColor groupTableViewBackgroundColor];
- summaryLabel.hidden = YES;
- //这句是设定一个回调函数reachability,当网络条件发生变化时则去调用reachabilityChanged
- [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(reachabilityChanged:) name: kReachabilityChangedNotification object: nil];
- //Change the host name here to change the server your monitoring
- remoteHostLabel.text = [NSString stringWithFormat: @"Remote Host: %@", @"www.apple.com"];
- //设定target地址,这里是www.apple.com
- hostReach = [[Reachability reachabilityWithHostName: @"www.apple.com"] retain];
- //启动网络条件检测
- [hostReach startNotifier];
- //更新UI的网络状态显示
- [self updateInterfaceWithReachability: hostReach];
- //探测是否能连上internet网
- internetReach = [[Reachability reachabilityForInternetConnection] retain];
- [internetReach startNotifier];
- [self updateInterfaceWithReachability: internetReach];
- //探测wifi是否开启
- wifiReach = [[Reachability reachabilityForLocalWiFi] retain];
- [wifiReach startNotifier];
- [self updateInterfaceWithReachability: wifiReach];
- [window makeKeyAndVisible];
- }
- //如需要查看网络状态,如下调用即可
- NetworkStatus netStatus = [curReach currentReachabilityStatus];
- netStatus有ReachableViaWWAN(蜂窝网络3G之类的),ReachableViaWiFi(wifi连接),NotReachable(无法连接)
关于在iOS设备上探测WIFI,3G,GPRS使用情况的细节的更多相关文章
- 不通过App Store,在iOS设备上直接安装应用程序(转)
今天在iOS设备上安装天翼云存储app,在safari上直接打开http://cloud.189.cn/wap/index.jsp,点击“点击免费安装”,如下图: 神奇的事情发生了,设备上直接下载ap ...
- jquery keyup 在IOS设备上输入中文时不触发
今天做一个异步查询功能的时候发现在IOS设备上查询中文时keyup没有触发,在其他设备上时可以的,后来在stackoverflow上找到下面这种解决方法,贴出来算是抛砖引玉了. $h_input.on ...
- 【转】使IFRAME在iOS设备上支持滚动
原文链接: Scroll IFRAMEs on iOS原文日期: 2014年07月02日 翻译日期: 2014年07月10日翻译人员: 铁锚 很长时间以来, iOS设备上Safari中超出边界的元素将 ...
- 使IFRAME在iOS设备上支持滚动
原文链接: Scroll IFRAMEs on iOS原文日期: 2014年07月02日 翻译日期: 2014年07月10日翻译人员: 铁锚很长时间以来, iOS设备上Safari中超出边界的元素将不 ...
- iOS设备上出现的click,live,on点击失去效果
iOS设备上出现的点击事件失效,但是在Android上可以正常使用, 1.iOS设备对标签点击限制,不认为是可点击的标签,需要给要绑定点击事件的标签加上一个样式,cursor:pointer:这样就可 ...
- 怎样将游戏从Unity导到iOS设备上
当我开始开发自己的iOS游戏时,我会考虑的第一件事便是如何将其导出到设备中,如此有效地测试我的游戏.最初,该过程看似很长且复杂,我所遇到的主要问题是,尽管存在许多资源,但是它们并非完全来自同样的地方, ...
- 不通过AppStore,在iOS设备上直接安装应用程序的原理
本文转载至 http://mobile.51cto.com/hot-439095.htm 通过itms-services协议,可以通过safari浏览器直接在iOS设备上安装应用程序.利用这种方式, ...
- 在Windows笔记本上调试运行在iOS设备上的前端应用
我在每天工作中需要在不同的移动设备上测试我们开发的前端应用是否正常工作,比如iOS设备和Android设备.我用的工作笔记本电脑又是Lenovo的,安装的是Windows操作系统. 有的时候一个开发好 ...
- 在IOS设备上POST提交form表单,后台接收不到值怎么办?
原文:https://blog.csdn.net/xhaimail/article/details/90440029 最近在工作上遇到一个奇葩问题,在Android和Windows平台上做请求时参数都 ...
随机推荐
- 在终端更改MAC的MySQL的root密码
- 装饰器与lambda
装饰器 实际上理解装饰器的作用很简单,在看core python相关章节的时候大概就是这种感觉.只是在实际应用的时候,发现自己很难靠直觉决定如何使用装饰器,特别是带参数的装饰器,于是摊开来思考了一番, ...
- Selenium WebDriver-通过键盘事件操作浏览器
#encoding=utf-8 import unittest import time import chardet from selenium import webdriver class Visi ...
- 深入新版BS4源码 探索flex和工程化sass奥秘
你可能已经听说了一个“大新闻”:Bootstrap4 合并了代号为#21389的PR,宣布放弃支持IE9,并默认使用flexbox弹性盒模型.这标志着:1)前端开发全面步入“现代浏览器”的时代进一步来 ...
- Spring中的注解 @Qualifier
在使用Spring框架中@Autowired标签时默认情况下使用 @Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个.当找不到一个匹配的 Bean ...
- 【图文】 使用ant编译和发布java项目
开发JavaEE项目经常会碰到修改代码后,项目没有重新编译的问题.老大给指明了一个解决办法:用ant编译项目. ant是apache基金会下的一个项目,是基于Java语言的构建工具. ...
- Welcome-to-Swift-06函数(Functions)
函数是执行特定任务的代码自包含块.给定一个函数名称标识, 当执行其任务时就可以用这个标识来进行"调用". Swift的统一的功能语法足够灵活来表达任何东西,无论是甚至没有参数名称的 ...
- sklearn python API
sklearn python API LinearRegression from sklearn.linear_model import LinearRegression # 线性回归 # modul ...
- centos中简易安装docker
centos中简易安装docker准备环境要求:请确保自己的centos的内核版本大于3.10,使用如下linux命令: uname -r1显示如下类似信息: 3.10.0-862.3.3.el7.x ...
- 多态Poly中的向上/下转型 Upcast/Downcast
[参考资料]马克-to-win java中多态polymorphism,向上转型和动态方法调度有什么用? java中什么叫多态,动态方法调度(dynamic method dispatch)? jav ...