网络连接状态检测对于我们的iOS app开发来说是一个非常通用的需求。为了更好的用户体验,我们会在无网络时展现本地或者缓存的内容,并对用户进行合适的提示。但事实上,当前iOS开发者们普遍使用的网络检测框架,实际上都无法帮助我们检测真正的网络连接状态;它们所能检测的只是本地连接状态。 本地连接状态和实际网络连接状态不一致的“伪连接”情况包括但不限于如下场景:
很多国内外的网友关于此问题早有提问和吐槽,比如:
为了着手解决此类问题,笔者希望就此打造一个通用、简单、可靠并且能检测实际网络连接状态的框架,从而帮助提升app在上述场景下的用户体验;这就是 RealReachability 的由来。
RealReachability是笔者1个月之前发布到github的开源库,项目地址如下: https://github.com/dustturtle/RealReachability。
短短1个月时间收获了几百个star,最近还上了github的 oc板块趋势排行榜 ,开发者们对此框架的热情完全出乎了笔者的意料;这也正说明此框架抓住了开发者们的痛点。
此框架开发的初衷来源于项目实际需求,离线模式对网络连接状态的要求比较苛刻,且实际场景经常会遇到“伪连接”的情况,项目中所使用的Reachability面对此场景力不从心。多方研究后引入了ping能力(此方案流量开销最小,也最简单),实现了简单的实际网络连接监测;后面将ping的能力和本地网络检测有机的结合,并且在实时性和开销上达成了一个平衡,不断提炼和优化,于是有了这个框架。
可以告诉大家的是,这个框架在appstore上架应用中已经经受了考验,且经过了长时间的测试,可以放心使用;目前也已经有很多开发者朋友们在其app中使用了我们的框架(让笔者略感自豪的是,他们来自世界各地!)。
RealReachability主要包含3大模块:connection、ping、FSM;
其中Ping模块通过对同样是苹果提供的ping样例代码进行了封装,connection模块实现了基于SCNetworkReachability的本地状态检测,FSM模块是有限状态机。
通过FSM的状态管理控制connection模块和Ping模块协同工作,剔除了重复的状态变化,并通过可配置的定时策略等业务逻辑优化,权衡了实时性和开销,最终得到了我们的实现。PS:其中connection模块和ping模块也可独立使用,分别提供本地网络检测和ping的能力。
感兴趣的读者也可以尝试(调用方式请参考RealReachability开源代码)。
我们致力于打造一个打造一个通用、简单、可靠并且能检测实际网络连接状态的框架,从而帮助app开发者们在各种伪连接的场景下,也能够检测出网络真实的可达性,从而优化app的体验;现代架构的移动app大部分是胖客户端,即使离开了网络,也能提供很大一部分功能。RealReachability的能力也限于此。比如网速检测、个人热点信息检查等功能,不是此框架的设计目标,也超出了其能力范围。
localconnection是基于本地的检测,因此其带来的开销可以忽略;ping模块的单次ICMP探测包大小仅为64字节(包含包头部),探测的频率默认为2分钟1次,对于客户端来说1小时的应用前台运行仅额外消耗2kb的流量,完全忽略不计;对于server端来说,如此低频率、低流量的分布式ICMP包,也不会带来压力:对比正常动辄几十kb甚至更多大小的请求,可以说是九牛一毛。
其接口的设计和调用方法和Reachability非常相似,大家可以无缝上手,非常方便。 开启网络监听:
[GLobalRealReachability startNotifier]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(networkChanged:) name:kRealReachabilityChangedNotification object:nil];
关闭网络监听:
[GLobalRealReachability stopNotifier];
回调代码示例:
- (void)networkChanged:(NSNotification *)notification { RealReachability *reachability = (RealReachability *)notification.object; ReachabilityStatus status = [reachabilitycurrentReachabilityStatus]; NSLog(@"currentStatus:%@",@(status)); }
查询当前实际网络连接状态:
ReachabilityStatus status = [reachabilitycurrentReachabilityStatus];
手动触发实时网络状态查询,可以在block回调中处理自己的业务(特别是网络请求操作),此接口的block会被异步调用。代码示例:
[GLobalRealReachabilityreachabilityWithBlock:^(ReachabilityStatus status) { switch (status) { caseRealStatusNotReachable: { // case NotReachable handler break; } caseRealStatusViaWiFi: { // case WiFi handler break; } caseRealStatusViaWWAN: { // case WWAN handler break; } default: break; } }];
手动设置目标host地址(ping探测的目标地址):
GLobalRealReachability.hostForPing = @"www.baidu.com";
注意:需要确保该host地址可以被ping探测到。此操作为可选,默认的目标host地址为www.baidu.com。
手动设置自动探测间隔(autoCheckInterval,单位为分钟):
GLobalRealReachability.autoCheckInterval = 3.0f;
注意:此处根据应用的实时性要求来设置自动探测的间隔,实时性要求较高时可适当调低此参数,但不建议设置为1.0以下。
希望这个框架能够帮助到大家的iOS开发! 遇到任何疑问或者使用上的问题,都可以联系我(管振纬/游族iOS高级工程师),期待与您交流iOS开发技术: [email protected]
对此框架我也会持续进行维护和优化,更希望感兴趣的朋友可以到github上pull request! 开源有你更精彩!
RealReachability
本文原作者:管振纬/游族iOS高级工程师
作者QQ群:494669518
原作者 管振纬 授权标哥的技术博客发表本篇博文。
关注 | 账号 | 备注 |
---|---|---|
Swift/ObjC技术群一 | 324400294 | 群一若已满,请申请群二 |
Swift/ObjC技术群二 | 494669518 | 群二若已满,请申请群三 |
Swift/ObjC技术群三 | 461252383 | 群三若已满,会有提示信息 |
关注微信公众号 | iOSDevShares | 关注微信公众号,会定期地推送好文章 |
关注新浪微博账号 | 标哥Jacky | 关注微博,每次发布文章都会分享到新浪微博 |
关注标哥的GitHub | CoderJackyHuang | 这里有很多的Demo和开源组件 |
关于我 | 进一步了解标哥 | 如果觉得文章对您很有帮助,可捐助我! |
版权声明:本文为【标哥的技术博客】原创出品,欢迎转载,转载时请注明出处!