在项目中实现网络的实时监测有两种方式:一种是采用第三方网络请求的网络检测方法,一种是使用OC自带的网络检测方法。我项目中采用的是第二种。
具体方法如下:
1、采用AF的网络检测,并实时发送通知,以达到网络实时监测的目的。
+ (AFNetworkReachabilityManager *)reachability
{
// 1.获得网络监控的管理者
AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
// 2.设置网络状态改变后的处理
[mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
// 当网络状态改变了, 就会调用这个block
switch (status) {
case AFNetworkReachabilityStatusUnknown: // 未知网络
NSLog(@"未知网络");
[[NSNotificationCenter defaultCenter] postNotificationName:@"NoNetWorkNotification" object:nil userInfo:@{@"flag":@1}];
break;
case AFNetworkReachabilityStatusNotReachable: // 没有网络(断网)
NSLog(@"没有网络(断网)");
[[NSNotificationCenter defaultCenter] postNotificationName:@"NoNetWorkNotification" object:nil userInfo:@{@"flag":@0}];
break;
case AFNetworkReachabilityStatusReachableViaWWAN: // 手机自带网络
NSLog(@"手机自带网络");
[[NSNotificationCenter defaultCenter] postNotificationName:@"NoNetWorkNotification" object:nil userInfo:@{@"flag":@1}];
break;
case AFNetworkReachabilityStatusReachableViaWiFi: // WIFI
NSLog(@"WIFI");
[[NSNotificationCenter defaultCenter] postNotificationName:@"NoNetWorkNotification" object:nil userInfo:@{@"flag":@1}];
break;
}
}];
// 3.开始监控
[mgr startMonitoring];
return mgr;
}
代码写在网络请求的最底层,但是只有在调用单例的时候才会触发网络的检测,并且是以回调的时候进行网络的检测,所以个人觉得这种方法比较适合用来判断是否进行网络请求,不适合实时的网络监测用来改变页面布局。
2、OC自带的网络检测——Reachability。(https://developer.apple.com/library/ios/samplecode/Reachability/Reachability.zip)
Reachability的使用,首先将Reachability.h及Reachability.m导入工程,其次AppDelegate.h中添加头文件,之后需要导入SystemConfiguration.framework,最后就是代码了。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSUserDefaults * user = [NSUserDefaults standardUserDefaults];
[user setObject:@1 forKey:NETWORK];
[user synchronize];
//设置网络检测的站点
NSString * remoteHostName = @"www.baidu.com";
self.reachablity = [Reachability reachabilityWithHostName:remoteHostName];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachablityStatusChange:) name:kReachabilityChangedNotification object:nil];
[self.reachablity startNotifier];
return YES;
}
-(void)reachablityStatusChange:(NSNotification *)notification
{
Reachability * curReach = [notification object];
// NSParameterAssert([curReach isKindOfClass:[Reachability class]]);(此处不注释掉网络有变化的时候代码直接crash了,不清楚为什么)
[self updateInterfaceWithReachablity:curReach];
}
-(void)updateInterfaceWithReachablity:(Reachability *)reachablity
{
if(reachablity == _reachablity)
{
NSUserDefaults * user = [NSUserDefaults standardUserDefaults];
NetworkStatus netStatus = [reachablity currentReachabilityStatus];
switch (netStatus) {
case NotReachable:{
[user setObject:@0 forKey:NETWORK];
[[NSNotificationCenter defaultCenter] postNotificationName:NETWORKCHANGE object:nil userInfo:@{NETWORK:@0}];
}
break;
case ReachableViaWWAN:{
[user setObject:@1 forKey:NETWORK];
[[NSNotificationCenter defaultCenter] postNotificationName:NETWORKCHANGE object:nil userInfo:@{NETWORK:@1}];
}
break;
case ReachableViaWiFi:{
[user setObject:@1 forKey:NETWORK];
[[NSNotificationCenter defaultCenter] postNotificationName:NETWORKCHANGE object:nil userInfo:@{NETWORK:@1}];
}
break;
default:
break;
}
[user synchronize];
}
}
-(void)dealloc
{
[_reachablity stopNotifier];
}
这段代码里面为什么在发送通知的时候还需要存沙盒一份呢?原因是在无网络的情况下是没有必要进行网络请求的。但是如果在每个接口前都写一遍网络监测,那未免也太傻了,所以不如存一份,在进行最底层的网络请求前先取出来判断一下是否有网络再决定是否要继续进行数据请求。
网络已经检测了,随着网络的变化也发送通知了,在需要监测网络变化的页面添加监听,然后根据网络的变化调整页面布局或者数据请求貌似就好了,但是,其实还有一个潜在的问题,那就是当从无网状态恢复网络状态的时候,发送通知给各个页面,这个时候需要自动刷新数据,如果不做任何处理的话,各个页面会同时请求数据,但是其实我们只需要刷新当前页面的数据,其他页面,当进入那个页面的时候再刷新就好了。这个时候我们需要怎么做呢?
我采取的也是笨办法——通过标志位。进入页面置为YES,离开页面置为NO,当页面接收到通知的时候,只有标志位为YES的时候才会进行数据的请求,这样就解决网络恢复各个页面同时请求数据的问题了。个人觉得应该还会有更好的办法,但是目前还没有想到,之后再补充吧。