在項目中實現(xiàn)網(wǎng)絡(luò)的實時監(jiān)測有兩種方式:一種是采用第三方網(wǎng)絡(luò)請求的網(wǎng)絡(luò)檢測方法,一種是使用OC自帶的網(wǎng)絡(luò)檢測方法。我項目中采用的是第二種。
具體方法如下:
1、采用AF的網(wǎng)絡(luò)檢測,并實時發(fā)送通知,以達到網(wǎng)絡(luò)實時監(jiān)測的目的。
+ (AFNetworkReachabilityManager *)reachability
{
// 1.獲得網(wǎng)絡(luò)監(jiān)控的管理者
AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
// 2.設(shè)置網(wǎng)絡(luò)狀態(tài)改變后的處理
[mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
// 當網(wǎng)絡(luò)狀態(tài)改變了, 就會調(diào)用這個block
switch (status) {
case AFNetworkReachabilityStatusUnknown: // 未知網(wǎng)絡(luò)
NSLog(@"未知網(wǎng)絡(luò)");
[[NSNotificationCenter defaultCenter] postNotificationName:@"NoNetWorkNotification" object:nil userInfo:@{@"flag":@1}];
break;
case AFNetworkReachabilityStatusNotReachable: // 沒有網(wǎng)絡(luò)(斷網(wǎng))
NSLog(@"沒有網(wǎng)絡(luò)(斷網(wǎng))");
[[NSNotificationCenter defaultCenter] postNotificationName:@"NoNetWorkNotification" object:nil userInfo:@{@"flag":@0}];
break;
case AFNetworkReachabilityStatusReachableViaWWAN: // 手機自帶網(wǎng)絡(luò)
NSLog(@"手機自帶網(wǎng)絡(luò)");
[[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.開始監(jiān)控
[mgr startMonitoring];
return mgr;
}
代碼寫在網(wǎng)絡(luò)請求的最底層,但是只有在調(diào)用單例的時候才會觸發(fā)網(wǎng)絡(luò)的檢測,并且是以回調(diào)的時候進行網(wǎng)絡(luò)的檢測,所以個人覺得這種方法比較適合用來判斷是否進行網(wǎng)絡(luò)請求,不適合實時的網(wǎng)絡(luò)監(jiān)測用來改變頁面布局。
2、OC自帶的網(wǎng)絡(luò)檢測——Reachability。(https://developer.apple.com/library/ios/samplecode/Reachability/Reachability.zip)
Reachability的使用,首先將Reachability.h及Reachability.m導(dǎo)入工程,其次AppDelegate.h中添加頭文件,之后需要導(dǎo)入SystemConfiguration.framework,最后就是代碼了。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSUserDefaults * user = [NSUserDefaults standardUserDefaults];
[user setObject:@1 forKey:NETWORK];
[user synchronize];
//設(shè)置網(wǎng)絡(luò)檢測的站點
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]]);(此處不注釋掉網(wǎng)絡(luò)有變化的時候代碼直接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];
}
這段代碼里面為什么在發(fā)送通知的時候還需要存沙盒一份呢?原因是在無網(wǎng)絡(luò)的情況下是沒有必要進行網(wǎng)絡(luò)請求的。但是如果在每個接口前都寫一遍網(wǎng)絡(luò)監(jiān)測,那未免也太傻了,所以不如存一份,在進行最底層的網(wǎng)絡(luò)請求前先取出來判斷一下是否有網(wǎng)絡(luò)再決定是否要繼續(xù)進行數(shù)據(jù)請求。
網(wǎng)絡(luò)已經(jīng)檢測了,隨著網(wǎng)絡(luò)的變化也發(fā)送通知了,在需要監(jiān)測網(wǎng)絡(luò)變化的頁面添加監(jiān)聽,然后根據(jù)網(wǎng)絡(luò)的變化調(diào)整頁面布局或者數(shù)據(jù)請求貌似就好了,但是,其實還有一個潛在的問題,那就是當從無網(wǎng)狀態(tài)恢復(fù)網(wǎng)絡(luò)狀態(tài)的時候,發(fā)送通知給各個頁面,這個時候需要自動刷新數(shù)據(jù),如果不做任何處理的話,各個頁面會同時請求數(shù)據(jù),但是其實我們只需要刷新當前頁面的數(shù)據(jù),其他頁面,當進入那個頁面的時候再刷新就好了。這個時候我們需要怎么做呢?
我采取的也是笨辦法——通過標志位。進入頁面置為YES,離開頁面置為NO,當頁面接收到通知的時候,只有標志位為YES的時候才會進行數(shù)據(jù)的請求,這樣就解決網(wǎng)絡(luò)恢復(fù)各個頁面同時請求數(shù)據(jù)的問題了。個人覺得應(yīng)該還會有更好的辦法,但是目前還沒有想到,之后再補充吧。